Symfony 从外部实体存储库生成实体属性
我有一个用户实体,可以向他的客户收费。因此,用户可以创建发票实体。我想做的是,通过计算发票总额,轻松检索用户已收取的费用。通过将$user变量传递给汇总这些发票的方法,我可以在我的发票存储库中轻松做到这一点。但是我想把这个值存储在用户实体中,所以在我的小树枝模板中,我可以用类似这样的东西调用它:{{app.User.chargedAmount} 但据我所知,我无法在我的用户实体中创建getChargedAmount(),它将使用发票存储库并设置受保护的$chargedAmount属性Symfony 从外部实体存储库生成实体属性,symfony,doctrine-orm,repository,entity,Symfony,Doctrine Orm,Repository,Entity,我有一个用户实体,可以向他的客户收费。因此,用户可以创建发票实体。我想做的是,通过计算发票总额,轻松检索用户已收取的费用。通过将$user变量传递给汇总这些发票的方法,我可以在我的发票存储库中轻松做到这一点。但是我想把这个值存储在用户实体中,所以在我的小树枝模板中,我可以用类似这样的东西调用它:{{app.User.chargedAmount} 但据我所知,我无法在我的用户实体中创建getChargedAmount(),它将使用发票存储库并设置受保护的$chargedAmount属性 我应该如何
我应该如何在我的用户实体中存储此自定义值?在您的用户存储库中,您可以创建一个自定义查询(例如
findChargedAmount
)来检索已收费金额
public function findChargedAmount($user)
{
$em = $this->getEntityManager();
$query = $em->createQuery('SELECT SUM(i.total) AS amount FROM MyBundle:Invoice i WHERE i.user = :user');
$query->setParameter('user', $user);
$sum = $query->getResult();
return $sum[0]['amount'];
}
假设发票实体作为用户的外键。您还可以使用一个
希望这会对您有所帮助。有几种方法可以做到这一点,但这两种方法都不会涉及实体中的存储库。(老实说,可能还有很多方法可以做到这一点)
oneToMany
关联的,那么您的用户模型中可以有一个方法,该方法可以循环关联的发票,并动态获取金额。这意味着当前总数将不会持久化到数据库中
$totalCharged = null;
public function getTotalCharged()
{
if (null !== $totalCharged) {
return $totalCharged;
}
$totalCharged = 0;
foreach ($this->getInvoices() as $invoice) {
$totalCharged += $invoice->getTotal();
}
return $totalCharged;
}
class AcmeExtension extends \Twig_Extension
{
protected $invoiceRepository;
public function __construct(EntityRepository $invoiceRepository)
{
$this->invoiceRepository = $invoiceRepository;
}
public function getFunctions()
{
return array(
new \Twig_SimpleFunction(
'acme_invoice_total_charged',
array($this, 'getTotalChargedForUser')
),
);
}
public function getTotalChargedForUser(UserInterface $user)
{
return $this->invoiceRepository->getTotalChargedForUser($user);
}
public function getName()
{
return 'acme_invoice_extension';
}
}
use Doctrine\ORM\EntityRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
class UserInvoiceTotalChargedSubscriber implements EventSubscriberInterface
{
protected $invoiceRepository;
public function __construct(EntityRepository $invoiceRepository)
{
$this->invoiceRepository = $invoiceRepository;
}
public static function getSubscribedEvents()
{
return array(
'acme.invoice.create' => 'updateTotalCharged',
'acme.invoice.update' => 'updateTotalCharged',
'acme.invoice.remove' => 'updateTotalCharged',
);
}
public function updateTotalCharged(GenericEvent $event)
{
$invoice = $event->getSubject();
if (!$invoice instanceof InvoiceInterface) {
// Or Invoice if you are not using interfaces
throw new \Exception(
sprintf('Invoice expected, %s provided', get_class($invoice)
);
}
$user = $invoice->getUser();
$totalCharged = $this->invoiceRepository
->getTotalChargedForUser($user);
$user->setTotalCharged($totalCharged);
// This could be moved to a separate class that performed the
// calculation instead where you could call it like
// $this->totalChargedCalculator->calculate($invoice->getUser());
// Obviously this would need to be injected instead of the repository
}
}
{{acme\u invoice\u total\u charged(user)}}
,尽管这并不提供相同的可移植性。这(与选项1类似)意味着当前总数不会持久化到数据库中
$totalCharged = null;
public function getTotalCharged()
{
if (null !== $totalCharged) {
return $totalCharged;
}
$totalCharged = 0;
foreach ($this->getInvoices() as $invoice) {
$totalCharged += $invoice->getTotal();
}
return $totalCharged;
}
class AcmeExtension extends \Twig_Extension
{
protected $invoiceRepository;
public function __construct(EntityRepository $invoiceRepository)
{
$this->invoiceRepository = $invoiceRepository;
}
public function getFunctions()
{
return array(
new \Twig_SimpleFunction(
'acme_invoice_total_charged',
array($this, 'getTotalChargedForUser')
),
);
}
public function getTotalChargedForUser(UserInterface $user)
{
return $this->invoiceRepository->getTotalChargedForUser($user);
}
public function getName()
{
return 'acme_invoice_extension';
}
}
我想我会选择选项1。我不需要将此值存储在数据库中,因此选项2对我来说似乎有些过分。选项#3的可移植性不够,将来我可能需要在小枝模板之外的信息。我将在您的示例中添加一些测试#1认为,因为我只想对已付款发票求和(状态=3)。我唯一不喜欢您的解决方案的地方是我必须使用PHP(状态、年份等)应用我的过滤器,而不是在db查询中。看起来有点重。老实说,我会选择2号,但只有在您已经使用事件订阅服务器的情况下,它才有意义。总是可以选择使用条令事件订阅者来监听对实际实体的更新,而不是自定义事件。这正是我在原始帖子中提到的。问题是这个值不能存储在用户实体中(不一定存储在DB中,只存储在PHP对象中)。因此,每次我想使用它时,我都必须调用该方法,而不是只调用{{app.user.getChargedAmount}},并将其传递给我的模板。此外,我不能像Qoop的解决方案#1那样“缓存”它。