【问题标题】:Doctrine cascade persist from inversed side学说级联从反面持续存在
【发布时间】:2023-04-07 03:15:01
【问题描述】:

我与关联表有“多对多”关系。父表中的函数 calculDesCouts() 正在计算 原料的总成本,并将此信息保存在字段中。实际上,由于关系的拥有和反面,当成分价格发生变化时,我无法级联持久化父表。

这样做的正确方法是什么?我的意思是,当子行更新时,如何从父表触发持久回调?我知道我可以在我的控制器中做到这一点,在所有使用这种成分的食谱上都有一个循环,但我真的很想在 ORM 层上做到这一点......

这是我的父实体,在 calculDesCouts 上有一个生命周期回调:

<?php

/**
 * @ORM\Table(name="recette")
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class Recette
{

  /**
   * @ORM\Column(type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /** 
   * @ORM\OneToMany(targetEntity="\My\AcmeBundle\Entity\RecetteIngredientAssociation", mappedBy="recette", cascade={"persist"}) 
   */
  protected $recette_ingredient_associations;

  /**
   * @ORM\Column(type="decimal", scale=2, nullable=true)
   */
  private $cout_nourriture;

  /** 
   * @ORM\PrePersist
   * @ORM\PreUpdate
   */
  public function calculDesCouts()
  {
    $this->cout_nourriture = 0;

    foreach ($this->recette_ingredient_associations as $ria) {
      $this->cout_nourriture += $ria->getIngredient()->getPrix() * $ria->getQuantite();
    }

  }
}

这是我的关联实体:

<?php

/**
 * @ORM\Table(name="recette_ingredient_association")
 * @ORM\Entity
 */
class RecetteIngredientAssociation
{

  /**
   * @ORM\Column(type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\ManyToOne(targetEntity="\My\AcmeBundle\Entity\Recette", inversedBy="recette_ingredient_association")
   * @ORM\JoinColumn(name="recette_id", referencedColumnName="id")
   *
   */
  private $recette;

  /**
   * @ORM\ManyToOne(targetEntity="\My\AcmeBundle\Entity\Ingredient", inversedBy="recette_ingredient_association")
   * @ORM\JoinColumn(name="ingredient_id", referencedColumnName="id")
   */
  private $ingredient;

  /**
   * @ORM\Column(type="decimal", scale=2, nullable=false)
   */
  private $quantite;

}

这是我的子实体:

<?php

/**
 * @ORM\Table(name="ingredient")
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class Ingredient
{

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="decimal", scale=2, nullable=true)
     */
    private $prix;

    /** 
     * @ORM\OneToMany(targetEntity="\My\AcmeBundle\Entity\RecetteIngredientAssociation", mappedBy="ingredient") 
     */
    protected $recette_ingredient_associations;

}

【问题讨论】:

  • 不清楚你要归档什么。您是否将总成本存储在数据库中?如果是,它不会反映在发布的代码中。如果不是,并且每次调用时它只是在运行中计算,那么我认为没有必要触发任何东西。每次成分价格发生变化时,盘子的总成本都会反映这种变化
  • 我已使用 $cout_nourriture 列更新了来自父实体的示例代码。是的,计算的字段必须存储在数据库中,这就是它需要重新计算的原因。 (抱歉英语不好:()

标签: symfony doctrine-orm cascade


【解决方案1】:

我不知道如何在 ORM 级别上实现,但我会在 Symfony2 层上实现。 要做到这一点,您需要创建一个 EventListener,它会在成分更新的情况下调用 Recette 的 calculDesCouts。

就像声明一个服务:

 app.ingredient_listener_update:
      class: AppBundle\Listener\IngredientPriceListener
      tags:
          - { name: doctrine.event_listener, event: postUpdate }

并在这个 AppBundle\Listener\IngredientPriceListener 中创建一个方法

public function postUpdate(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();

    $em = $args->getEntityManager();

    if ($entity instanceof Ingredient) {

        foreach ($entity->get_recette_ingredient_associations() as $association) 
            foreach ($association->get_recettes() as $recette) {
                $recette->calculDesCouts();
                $em->persist($recette);
            }
    }
}

【讨论】:

  • 谢谢!我认为它是最好的解决方案,并且对您的代码进行一些更改,它可以正常工作!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 2011-07-21
相关资源
最近更新 更多