php - Symfony 学说不会滋润整个链条
问题描述
我在下面尽可能简化了我的 3 个实体,它显示了一个简单的关系Currency <- 1:1 -> Balance <- 1:N -> BalanceLog
实体/货币.php
/**
* @ORM\Entity(repositoryClass=CurrencyRepository::class)
*/
class Currency
{
/**
* @ORM\Id
* @ORM\Column(type="string", length=3)
*/
private ?string $code;
/**
* @ORM\OneToOne(targetEntity="Balance", mappedBy="currency")
**/
private ?Balance $balance;
// ...
}
实体/余额.php
/**
* @ORM\Entity(repositoryClass=BalanceRepository::class)
*/
class Balance
{
/**
* @ORM\Id
* @ORM\OneToOne(targetEntity="Currency", inversedBy="balance")
* @ORM\JoinColumn(name="currency", referencedColumnName="code", nullable=false)
**/
private ?Currency $currency;
/**
* @ORM\OneToMany(targetEntity="App\Entity\BalanceLog", mappedBy="balance")
*/
private Collection $balance_logs;
// ...
}
实体/BalanceLog.php
/**
* @ORM\Entity(repositoryClass=BalanceLogRepository::class)
*/
class BalanceLog
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Balance", inversedBy="balance_logs")
* @ORM\JoinColumn(name="balance_currency", referencedColumnName="currency")
**/
private ?Balance $balance;
// ...
}
当我打电话时会出现问题:
$balanceLog = $this->getDoctrine()
->getRepository('App:BalanceLog')->findAll();
这将水合BalanceLog::$balance
到类型的正确实例Balance
,但它不会水合BalanceLog::$balance->currency
到Currency
实例。相反,它只想string
使用
导致错误:
类型化属性 App\Entity\Balance::$currency 必须是 App\Entity\Currency 的实例或 null,使用的字符串
肮脏的解决方法是使 Balance::$currency 没有固定类型的?Currency
. 然后它将接受字符串和代码“有效”。但这是不正确的。Balance::$currency
应该是类型,Currency
有时不是字符串,有时是货币。
我试图在 中制作自己的方法BalanceLogRepository
,无论出于何种原因,这都很好:
public function findByBalance(Balance $balance) : iterable
{
$query = $this->createQueryBuilder('bl');
$query->andWhere('bl.balance = :balance')
->setParameter('balance', $balance);
return $query->getQuery()->getResult();
}
所以我更加困惑为什么默认findAll
或者findBy
不做递归水化
经过进一步调查,我发现了一个非常奇怪的行为:
如果我添加此代码:
$balance = $this->getDoctrine()->getRepository('App:Balance')->find('USD');
在...前面
$balanceLog = $this->getDoctrine()->getRepository('App:BalanceLog')->findAll();
在我的控制器中,错误消失了。就好像在我尝试先验地直接获取对象之前,没有正确加载具有依赖关系的App:Balance
ORM 模式。Balance
Balance
解决方案
我做了一些调试,它看起来BalanceLog
并没有创建一个完整的Balance
实体实例,而是一个代理。解决方案是向BalanceLog
类添加急切加载
class BalanceLog
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Balance", inversedBy="balance_logs", fetch="EAGER")
* @ORM\JoinColumn(name="balance_currency", referencedColumnName="currency")
**/
private ?Balance $balance;
// ...
}
UnitOfWork.php然后不使用代理,而是将实体作为一个整体加载。
如果有人想知道为什么事先查询 Balance 可以使代码工作,那是因为 Doctrine 复杂的缓存机制。它保存Balance
了主键的实例USD
,然后在填充 BalanceLog 时,它使用此实例而不是创建代理。
我仍然认为 Proxy 不应该从 Entity 强制执行严格类型的属性,但这是 Doctrine 开发人员决定的事情。
推荐阅读
- python - 线程程序不退出
- json - Spark:输入 GenericRowWithSchema 时如何访问元素
- css - 如何在 Tailwind 中实现 font-variant-[caps,east-asian,ligatures]
- java - 我的游戏碰撞系统不能在多个图块上工作
- visual-studio-code - 是否可以在 VSCode 中打印到清晰的集成终端
- docker - 如何将域名和图像标签添加到 Dockerrun.aws.json 版本 2?
- python - python中的MACD图类似于tradingview图
- java - 从Android中的动态视图在SQLite中发送多个数据
- haskell - 一种将 Haskell 的 Either 类型推广到任意多种类型的方法?
- c# - 使用 if 和 do while 检测到的 C# 可访问代码