Doctrine 2与连接表中的其他列的多对多关系

gri*_*toi 7 php doctrine symfony

所以,我现在已经玩了一段时间使用学说并在一些基础项目中使用它,但我决定回过头来深入了解它能做些什么.

我现在决定切换到symfony 2作为我选择的框架,并且正在研究更深入的学说2可以做什么.

我一直试图解决的一件事是学说中的多对多关系.我开始建立一个配方系统,正在研究配方和配料之间的关系,这给了我3个实体,配方,配方成分和成分.我不能使用直接多对多关系的原因是因为我想在每个成分的连接表(单位和数量)中存储两个额外的列.

我目前遇到的问题是实体仍然存在,但是没有插入连接表中的recipe_id.我已经尝试了所有我能想到的东西,并通过每个线程和网站寻找答案.我确信这是我完全不知道的事情.请帮助,下面是我到目前为止的代码:

<?php
namespace Recipe\RecipeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
 * @ORM\Entity
 * @ORM\Table(name="recipe")
 * @ORM\HasLifecycleCallbacks()
 */
class Recipe{

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

/**
 * @ORM\OneToMany(targetEntity="RecipeIngredient", mappedBy="recipe", cascade=       {"persist"})
 */
protected $ingredients;
/**
 * @ORM\Column(type="string")
 * @var string $title
 *
 */
protected $title;
/**
 * Constructor
 */
public function __construct()
{
    $this->ingredients = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Add ingredients
 *
 * @param \Recipe\RecipeBundle\Entity\RecipeIngredient $ingredients
 * @return Recipe
 */
public function addIngredient(\Recipe\RecipeBundle\Entity\RecipeIngredient $ingredients)
{
    $ingredients->setRecipe($this);
    $this->ingredients[] = $ingredients;

    return $this;
}

/**
 * Remove ingredients
 *
 * @param \Recipe\RecipeBundle\Entity\RecipeIngredient $ingredients
 */
public function removeIngredient(\Recipe\RecipeBundle\Entity\RecipeIngredient $ingredients)
{
    $this->ingredients->removeElement($ingredients);
}

/**
 * Get ingredients
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getIngredients()
{
    return $this->ingredients;
}

/**
 * Set title
 *
 * @param string $title
 * @return Recipe
 */
public function setTitle($title)
{
    $this->title = $title;

    return $this;
}

/**
 * Get title
 *
 * @return string
 */
public function getTitle()
{
    return $this->title;
}
}
Run Code Online (Sandbox Code Playgroud)

和recipeIngredient

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

/**
 * @ORM\ManyToOne(targetEntity="Recipe", inversedBy="ingredients")
 * */
protected $recipe;

/**
 * @ORM\ManyToOne(targetEntity="Ingredient", inversedBy="ingredients" , cascade={"persist"})
 * */
protected $ingredient;

/**
 * @ORM\Column(type="string")
 * @var string  $quantity
 *
 */
protected $quantity;

/**
 * @ORM\Column(type="string")
 * @var string $unit
 *
 */
protected $unit;

/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Set quantity
 *
 * @param string $quantity
 * @return RecipeIngredient
 */
public function setQuantity($quantity)
{
    $this->quantity = $quantity;

    return $this;
}

/**
 * Get quantity
 *
 * @return string
 */
public function getQuantity()
{
    return $this->quantity;
}

/**
 * Set unit
 *
 * @param string $unit
 * @return RecipeIngredient
 */
public function setUnit($unit)
{
    $this->unit = $unit;

    return $this;
}

/**
 * Get unit
 *
 * @return string
 */
public function getUnit()
{
    return $this->unit;
}

/**
 * Set recipe
 *
 * @param \Recipe\RecipeBundle\Entity\Recipe $recipe
 * @return RecipeIngredient
 */
public function setRecipe(\Recipe\RecipeBundle\Entity\Recipe $recipe = null)
{
    $this->recipe = $recipe;

    return $this;
}

/**
 * Get recipe
 *
 * @return \Recipe\RecipeBundle\Entity\Recipe
 */
public function getRecipe()
{
    return $this->recipe;
}

/**
 * Set ingredient
 *
 * @param \Recipe\RecipeBundle\Entity\Ingredient $ingredient
 * @return RecipeIngredient
 */
public function setIngredient(\Recipe\RecipeBundle\Entity\Ingredient $ingredient = null)
{
    $this->ingredient = $ingredient;

    return $this;
}

/**
 * Get ingredient
 *
 * @return \Recipe\RecipeBundle\Entity\Ingredient
 */
public function getIngredient()
{
    return $this->ingredient;
}
}
Run Code Online (Sandbox Code Playgroud)

Lig*_*art 0

如果我正确理解这个模型,则配方的构造及其关联的配方成分是并发的。在您坚持之前,您可能没有 id,如果没有 id,则如果调用receipeIngredient->setRecipe(),则默认 null 将放置在recipeIngredient->recipe 字段中。这通常通过级联处理:“persist”(示例中的配方字段不存在,但您可以在控制器中显式处理它:

/** 
  * Creates a new Recipe entity.
  *
  */
public function createAction(Request $request)
{
  $em = $this->getDoctrine()->getManager();
  $form = $this->createForm(new RecipeType());  
  $form->bind($request);

  if ($form->isValid()){
    $data = $form->getData();
    $recipeId = $data->getId();
    $recipeIngredients=$data->getIngredients();
    $recipe=$em->getRepository('reciperecipeBundle:Recipe')
               ->findOneById($RecipeId);
    if (null === $Recipe)
      {$Recipe=new Recipe();}  
    foreach ($recipeIngredients->toArray() as $k => $i){
      $recipeIngredient=$em->getRepository('reciperecipeBundle:recipeIngredient')
                           ->findOneById($i->getId());
      if (null === $recipeIngredient)
        {$recipeIngrediente=new RecipeIngredient();}  
      $recipe->addIngredient($i);

      // Next line *might* be handled by cascade: "persist"        
      $em->persist($recipeIngredient);
    }  
    $em->persist($Recipe);
    $em->flush();
    return $this->redirect($this->generateUrl('Recipe', array()));
  }   

  return $this->render('reciperecipeBundle:Recipe:new.html.twig'
                      ,array('form'   => $form->createView()));  
}
Run Code Online (Sandbox Code Playgroud)