Doug
Doug

Reputation: 1890

One-Many-One Symfony2/Doctrine2 - How do I fill the fields in my many relation from the one side

Ok so I currently have set up a one-to-many-to-one relation over 3 tables:

Recipes-ProductRecipe-Products

###Recipes.yml###
oneToMany:
    products:
      targetEntity: ProductRecipe
      mappedBy: recipes
      cascade: ["all"]

###ProductRecipe.yml###
manyToOne:
    products:
      targetEntity: Products
      inversedBy: recipes
    recipes:
      targetEntity: Recipes
      inversedBy: products

###Products.yml###
  oneToMany:
    recipes:
      targetEntity: ProductRecipe
      mappedBy: products
      cascade: ["all"]

I have set up these entities using the built in command (doctrine:generate:entities) so I have all my setter/getters/_construct/_tostring in place.

Now I have all this set up (which works fine on it's own) I want the user to be able to add new products to a recipe from the recipe form. So I have made a collection of forms in the recipe form.

class RecipesType extends AbstractType{
    public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('recipename')
        ->add('recipedesc')
        ->add('recipeyeild')
        ->add('recipecost');
    $builder->add('products', 'collection', array(
'type' => new ProductRecipeType(),
'allow_add'    => true,));
}

Which connects to this form:

class ProductRecipeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('ammount')
        ->add('products')
    ;
}

And in my Recipes Controller I have this:

public function newAction()
{
    $entity = new Recipes();
    $pr = new ProductRecipe();
    $entity->getProducts()->add($pr);
    $form   = $this->createCreateForm($entity);

So far so good, the forms are created fine and persist to the database fine. However in my Many table the Recipe_ID field is not been filled with the recipe being created at that time. How do I fill that field on persist? Otherwise a user is creating a recipe and adding products to the recipe, but then when persisted I just have a new recipe with no products and a collection of product ammounts not connected to a recipe.

Sorry if I've written this up in a confusing way... It's because I'm confused myself.

EDIT

Just to help a little I'm adding my controllers code trimmed down a little:

class Recipes
{
private $id;
private $recipename;
private $recipedesc;
private $recipeyeild;
private $recipecost;
public function __construct()
{
    $this->products = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getId()
{
    return $this->id;
}
public function addProduct(\BC\InventoryBundle\Entity\ProductRecipe $pr)//<-this was $products
{
//$this->products[] = $products;  <-Original code now changed to below as suggested.

    $this->products->add($pr);
    $pr->setRecipes($this);    
    return $this;
}
public function removeProduct(\BC\InventoryBundle\Entity\ProductRecipe $products)
{
    $this->products->removeElement($products);
}
public function getProducts()
{
    return $this->products;
}

And my ProductRecipe entity:

class ProductRecipe
{
private $id;
private $ammount;
private $products;
private $recipes;
public function getId()
{
    return $this->id;
}
public function setAmmount($ammount)
{
    $this->ammount = $ammount;
    return $this;
}
public function getAmmount()
{
    return $this->ammount;
}
public function setProducts(\BC\InventoryBundle\Entity\Products $products = null)
{
    $this->products = $products;
    return $this;
}
public function getProducts()
{
    return $this->products;
}
public function setRecipes(\BC\InventoryBundle\Entity\Recipes $recipes = null)
{
    $this->recipes = $recipes;
    return $this;
}
public function getRecipes()
{
    return $this->recipes;
}

Edit 2

So after Cerad's suggestion I've got these...

//Recipes entity
 public function addProduct(\BC\InventoryBundle\Entity\ProductRecipe $products)
{

    $this->products->add($products);
    $products->setRecipes($this);

    return $this;
}


//Recipes Controller
public function newAction()
{
    $entity = new Recipes();
    $products = new ProductRecipe(); 

    $entity->getProducts()->add($products);
    $entity->addProduct($products);

    $form = $this->createCreateForm($entity);

    return $this->render('BCInventoryBundle:Recipes:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ));
}

Still to no avail...

Edit 3

This Now works my issue was the majority of what I had in newAction should have been in the createAction. Works perfectly. Thank you Cerad.

Upvotes: 0

Views: 216

Answers (1)

Cerad
Cerad

Reputation: 48893

This is a common problem. You are never calling the ProductRecipe::setRecipe() method. Probably not calling setProduct either.

class Recipe
{
    public function addProduct($pr)
    {
        $this->products->add($pr);
        $pr->setRecipe($this); // *** This is what you need to add

In your controller:

$entity->addProduct($pr);

And while not directly relevant, consider changing Products and Recipes to Product and Recipe.

Upvotes: 1

Related Questions