I have two tables "RFQ" and "RFQitem". I can make form which can create RFQ with their title description and amount. And I can create RFQitem form which can create RFQitem with their title, description and amount.
Problems starts when I need to upgrade my RFQ form, so that I can make in it RFQitems which will saves in their table, but it need to be assigned to RFQ.
In symfony documentation is great example which actually works for me, but this is example is with task and their tags. So task there is with more than one attributes (name, description), but tags are only with one - name.
My RFQ entity with RFQItems looks like this:
/**
* #ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
* #ORM\JoinTable(name="rfq_item_title",
* joinColumns={#ORM\JoinColumn(name="rfq_item_title", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="id", referencedColumnName="id")}
* )
*/
protected $rfq_item_title;
/**
* #ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
* #ORM\JoinTable(name="rfq_item_description",
* joinColumns={#ORM\JoinColumn(name="rfq_item_description", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="id", referencedColumnName="id")}
* )
*/
protected $rfq_item_description;
/**
* #ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
* #ORM\JoinTable(name="rfq_item_amount",
* joinColumns={#ORM\JoinColumn(name="rfq_item_description", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="id", referencedColumnName="id")}
* )
*/
protected $rfq_item_amount;
But I know that this is wrong, but how I make ManyToMany relation with RFQitem which have more than one attributes?
The best way to go is to have this two entities as you are actually doing, the father and the collection childs with the attributtes you like, but do not get fixated to the Symfony example. It's a theoretical OOP, has not relations defined, so I'm going to make my best try to paste a coherent example based on a Theater->Works collection:
class Theater
{
private $name;
private $id;
/**
* Set name
* #param string $name
* #return Theater
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Get id
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $work;
/**
* Constructor
*/
public function __construct()
{
$this->work = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add work
*
* #param \Acme\RelationBundle\Entity\Work $work
* #return Theater
*/
public function addWork(\Acme\RelationBundle\Entity\Work $work)
{
$this->work[] = $work;
return $this;
}
/**
* Remove work
* #param \Acme\RelationBundle\Entity\Work $work
*/
public function removeWork(\Acme\RelationBundle\Entity\Work $work)
{
$this->work->removeElement($work);
}
/**
* Get work
* #return \Doctrine\Common\Collections\Collection
*/
public function getWork()
{
return $this->work;
}
}
Then the child entity Work:
class Work
{
// took out some comments to make it shorter
private $name;
private $description;
private $id;
/**
* Set name
* #param string $name
* #return Work
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Set description : And any others setters/getters with the attributes you want
* #param string $description
* #return Work
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get name
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Get description
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Get id
* #return integer
*/
public function getId()
{
return $this->id;
}
public function __toString()
{
return (string) $this->getName();
}
}
The trick is to use this Collection in Doctrine and then make a two Form Types, the parent and the childs, something like this example below.
TheatherType Formtype includes the Work childs:
$buider->add('rowswork', 'collection', array(
'type' => new WorkChildType(),
'allow_add' => true,
'allow_delete' => true,
)
);
So there is one row with their Work childs that have their own WorkChildType with the attributes from the entity. It's like a form, with an embedded array collection of items, in your case an "RFQ" father form and "RFQitem" childs.
Related
I am learning code testing (TDD) and wondering what should be tested for simple entities in Symfony?
From official documentation:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Category
*
* #ORM\Table(name="category")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
*/
class Category
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
private $products;
/**
* Constructor
*/
public function __construct()
{
$this->products = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add product
*
* #param \AppBundle\Entity\Product $product
*
* #return Category
*/
public function addProduct(\AppBundle\Entity\Product $product)
{
$this->products[] = $product;
return $this;
}
/**
* Remove product
*
* #param \AppBundle\Entity\Product $product
*/
public function removeProduct(\AppBundle\Entity\Product $product)
{
$this->products->removeElement($product);
}
/**
* Get products
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
}
Second:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="product")
*/
class Product
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
private $name;
/**
* #ORM\Column(type="decimal", scale=2)
*/
private $price;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Product
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set price
*
* #param string $price
*
* #return Product
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* #return string
*/
public function getPrice()
{
return $this->price;
}
/**
* Set description
*
* #param string $description
*
* #return Product
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set category
*
* #param \AppBundle\Entity\Category $category
*
* #return Product
*/
public function setCategory(\AppBundle\Entity\Category $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return \AppBundle\Entity\Category
*/
public function getCategory()
{
return $this->category;
}
}
I thought I had to create an Entity folder and within CategoryTest file:
namespace Tests\AppBundle\Entity;
use AppBundle\Entity\Tag;
use AppBundle\Form\DataTransformer\TagArrayToStringTransformer;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityRepository;
class CategoryTest extends \PHPUnit\Framework\TestCase
{
public function testGetName()
{
$category = new \AppBundle\Entity\Category();
$category->setName('test');
$this->assertSame('test', $category->getName());
}
}
So... In TDD I should testing all fields? For Product entity I should testing name, price and description?
If yes, how to deal with refactoring? In these cases I must use in all methods "$product = new Product();";
For a name field I might need to do another test? What?
Should I also test relationships or do it in functional tests?
It is a good practice to Entities have no (complex) logic inside. In fact it should be just representing your model. And since there is no logic, there is not much to test actually. When you check Symfony Demo app you will find no tests for entities and I believe it is done this way intentionally.
In case your application is not the only one using database I would consider writing functional tests for entities which will ensure you that someone else did not change database structure (for example by dropping column in table) without letting you know. One of possible ways to achieve that is running a simple query on table (entity) you are testing:
public function checkEntityDefinition($entityName)
{ $this->em->getRepository($entityName)
->createQueryBuilder('t')
->setMaxResults(1)
->getQuery()
->getArrayResult();
}
There are no assertion here but this will throw an exception when Entity definition does not match database
Given already persisted objects for categories. How do one reuse the existing categories in a one-to-many relationship in new objects when only the id of the cateories is known
/** #Entity() */
class Category {
/**
* #var string
* #\Doctrine\ORM\Mapping\Column(type="string")
*/
private $name;
/** #var string
* #\Doctrine\ORM\Mapping\Id()
* #\Doctrine\ORM\Mapping\Column(type="string")
*/
private $id;
/**
* Category constructor.
* #param string $name
* #param string $id
*/
public function __construct($name, $id)
{
$this->name = $name;
$this->id = $id;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return string
*/
public function getId()
{
return $this->id;
}
}
And now I have lets say two categories id=1 -> fiction and id=2 -> english book.
Now I know the ids of the categories and want to save the one-to-many relations in my Book object.
/** #Entity() */
class Book {
/** #var mixed
* #\Doctrine\ORM\Mapping\OneToMany()
*/
private $categories;
/** #var string */
private $title;
/**
* Book constructor.
* #param mixed $categories
* #param string $title
*/
public function __construct($categories, $title)
{
$this->categories = $categories;
$this->title = $title;
}
/**
* #return mixed
*/
public function getCategories()
{
return $this->categories;
}
/**
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
Is it possible to create and persist a book object by hand with references an existing and already persisted object from which I do only know the id?
You can't achieve this without retrieving at least a Reference proxy :
$categoriesRefs = ['english' => 1, 'fiction' => 2];
$categories = [];
foreach($categoriesRefs as $ref){
$categories[] = $em->getReference('Namespace\Entity\Category', $ref));
}
$book = new Book($categories, 'title');
$em->persist($book);
$em->flush();
You can store categories without fetching the whole Category objects.
Read more about reference proxy.
I have an application with Zend Framework2 and Doctrine2 as ORM.
I have this Entity called User:
namespace Adm\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User{
/**
* #ORM\Id
* #ORM\Column(type="integer");
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $name;
/**
* #ORM\Column(type="string")
*/
protected $email;
/**
* #ORM\Column(type="string")
*/
protected $password;
/**
* #ORM\ManyToMany(targetEntity="Module")
* #ORM\JoinTable(
* name="user_module",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="module_id", referencedColumnName="id")}
* )
*/
protected $modules;
public function __construct() {
$this->modules = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #return the $id
*/
public function getId() {
return $this->id;
}
/**
* #return the $name
*/
public function getName() {
return $this->name;
}
/**
* #return the $email
*/
public function getEmail() {
return $this->email;
}
/**
* #return the $password
*/
public function getPassword() {
return $this->password;
}
/**
* #param field_type $id
*/
public function setId($id) {
$this->id = $id;
}
/**
* #param field_type $name
*/
public function setName($name) {
$this->name = $name;
}
/**
* #param field_type $email
*/
public function setEmail($email) {
$this->email = $email;
}
/**
* #param field_type $password
*/
public function setPassword($password) {
$this->password = $password;
}
/**
* Add module
*
* #param dm\Entity\Module
* #return User
*/
public function addModules(Module $modules = null){
$this->modules[] = $modules;
}
/**
* Get modules
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getModules(){
return $this->modules;
}
}
See the modules property is a relation Many to Many with a table called user_modules.
And i have the Entity Module as well:
namespace Adm\Entity;
use Doctrine\ORM\Mapping as ORM;
class Module{
/**
* #ORM\Id
* #ORM\Column(type="integer");
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\Column(type="integer")
*/
private $status;
/**
* #return the $id
*/
public function getId() {
return $this->id;
}
/**
* #return the $name
*/
public function getName() {
return $this->name;
}
/**
* #return the $status
*/
public function getStatus() {
return $this->status;
}
/**
* #param field_type $id
*/
public function setId($id) {
$this->id = $id;
}
/**
* #param field_type $name
*/
public function setName($name) {
$this->name = $name;
}
/**
* #param field_type $status
*/
public function setStatus($status) {
$this->status = $status;
}
}
I receive a array variable containing the Post from a form to insert in a table. Each post element have it's property in Entity, as expected. Together, i have a $module variable which is an array containing id's of the modules. My question is: How do i insert this data in the user_module table?
My add function is this:
public function addUser($newUser){
$user = new User();
$user->setName($newUser['name']);
...
$this->getEm()->persist($user);
$this->getEm()->flush();
}
Firstly you need to have cascade={"persist"} as mentioned by #skrilled.
Then you need to retrieve the module entities from the database. You mentioned you have the id's in the $module variable.
You need a DQL statement something like this
$builder = $this->getEntityManager()->createQueryBuilder();
$builder->select('m')
->from('Adm\Entity\Module', 'm')
->where('m.id IN (:modules)')
->setParameter('modules', $modules);
$moduleEntities= $builder->getQuery()->getResult(Query::HYDRATE_OBJECT);
and in your User entity you will need
public function addModules(Array $moduleEntities)
{
foreach ($moduleEntities as $module) {
if ($module instanceof Module) {
$this->modules[] = $module;
}
}
return $this;
}
finally in your addUser method you will need to add the array of modules from the above DQL
public function addUser($newUser, $moduleEntities)
{
$user = new User();
$user->setName($newUser['name']);
....
$user->addModules($moduleEntities);
$this->getEm()->persist($user);
$this->getEm()->flush();
}
I hope this helps
You should read about using cascade. This will allow you to save/modify/remove the associated relationships and how you expect this to work.
In this case, you would want the relationship to persist since you want the associated entities to be saved when user itself is saved.
#ORM\ManyToMany(targetEntity="Module", cascade={"persist"})
http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html
By default, no operations are cascaded.
The following cascade options exist:
persist : Cascades persist operations to the associated entities.
remove : Cascades remove operations to the associated entities.
merge : Cascades merge operations to the associated entities.
detach : Cascades detach operations to the associated entities.
refresh : Cascades refresh operations to the associated entities.
all : Cascades persist, remove, merge, refresh and detach operations to associated entities.
I have problem with the bundle "a2lix/translation-form-bundle" while using MongoDB in Symfony 2.5. I think I've done everything like it was in the documentation, but I have "The required option "class" is missing." error.
My Product:
/**
* Class Product
* #MongoDB\Document(repositoryClass="MyBundle\ProductBundle\Repository\ProductRepository")
* #Gedmo\TranslationEntity(class="MyBundle\ProductBundle\Document\ProductTranslation")
*/
class Product implements Translatable
{
/**
* #MongoDB\Id
*
*/
protected $id;
/**
* #MongoDB\String
* #Gedmo\Translatable
*/
protected $name;
/**
*
* #MongoDB\ReferenceMany(targetDocument="MyBundle\ProductBundle\Document \ProductTranslation", mappedBy="object", cascade={"all"})
*
*/
private $translations;
public function __construct()
{
$this->translations = new ArrayCollection();
}
public function __toString()
{
return $this->getName();
}
/**
* Get id
*
* #return id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return self
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string $name
*/
public function getName()
{
return $this->name;
}
/**
* Set translations
*
* #param ArrayCollection $translations
* #return Product
*/
public function setTranslations($translations)
{
foreach ($translations as $translation) {
$translation->setObject($this);
}
$this->translations = $translations;
return $this;
}
/**
* Get translations
*
* #return ArrayCollection
*/
public function getTranslations()
{
return $this->translations;
}
And this is my ProductTranslation:
class ProductTranslation extends AbstractPersonalTranslation
{
/**
* #MongoDB\ReferenceOne(targetDocument="MyBundle\ProductBundle\Document\Product", inversedBy="translations")
*
*/
public $object;
}
I'm still getting that "The required option "class" is missing." error and I don't know what is a problem.
You get this error because MongoDB ODM Mapping creates a field mapping on Reference.
For example, when you have a ManyToOne or OneToMany relation ORM doesn't create field mapping.
So a2lix sees your object field as usual mapped field. As the form builder resolves this object field like document type so you need to provide the class option to make it work.
But if you would provide this option then your object field will be rendered as translatable field and it definitely sucks.
So please try this:
->add('translations', 'a2lix_translations', [
'exclude_fields' => [
'object',
]
])
It will help you with this particular issue.
I made a web application with Symfony2, in which a User has an array correlation ManytoMany with the entity Mission. The User can upload the entity $product through a form, and one of the data passed by the form is the mission associated to the user.
There are more than only one mission for every user; so, when he uploads a $product object, he should also be able to select the mission he prefers.
To upload the file I use a form in a controller in the following way:
$form = $this->createFormBuilder($product)
->add('mission', 'entity', array('required' => true, 'multiple' => false, 'class' => 'AcmeManagementBundle:Mission', 'query_builder' => function($repository) { return $repository->createQueryBuilder('c')->orderBy('c.id', 'ASC'); },))
//...
->add('save', 'submit')
->getForm();
It works, but not fine: indeed in this field I can select all the mission stored, and not only the ones associated with the user.
I tried then with:
$form = $this->createFormBuilder($product)
->add('mission', 'collection', array('required' => true) )
//...
->add('save', 'submit')
->getForm();
It works but shows only one mission, and doesn't allow the user to select the preferred mission.
I tried also with:
->add('mission', 'collection', array('required' => true) )
but it tells me:
Neither the property "missions" nor one of the methods "getMissions()",
"isMissions()", "hasMissions()", "__get()" exist and have public access
in class "Acme\GroundStationBundle\Entity\Product".
How I should change my controller??
My product entity is:
class Product
{
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", mappedBy="product")
*/
protected $mission;
//...
/**
* Set mission
*
* #param string $mission
* #return Product
*/
public function setMission($mission)
{
$this->mission = $mission;
return $this;
}
/**
* Get mission
*
* #return string
*/
public function getMission()
{
return $this->mission;
}
//...
UPDATE ---
I will post also my product and mission entity, as asked in the comments
This is my User Entity is:
abstract class User extends BaseUser
{
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", inversedBy="users", orphanRemoval=true)
* #ORM\JoinTable(name="user_mission")
*/
private $missions;
/**
* Add missions
*
* #param \Acme\ManagementBundle\Entity\Mission $missions
* #return User
*/
public function addMission(\Acme\ManagementBundle\Entity\Mission $missions)
{
$this->missions[] = $missions;
return $this;
}
//...
And my Mission Entity:
<?php
namespace Acme\ManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* #ORM\Entity
*/
class Mission {
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #var integer
*/
protected $id;
/**
* #ORM\Column(type="string", length=60)
* #var String
*/
protected $name;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\ManyToOne(targetEntity="Acme\GroundStationBundle\Entity\Product", inversedBy="mission")
* #ORM\JoinColumn(name="productId", referencedColumnName= "id")
*/
private $product;
/**
* #ORM\Column(type="string", length=600)
* #var String
*/
protected $description;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\User", mappedBy="missions", cascade={"all"}, orphanRemoval=true)
*/
private $users;
public function __construct(){
$this -> users = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Mission
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set description
*
* #param string $description
* #return Mission
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Add users
*
* #param \Acme\ManagementBundle\Entity\User $users
* #return Mission
*/
public function addUser(\Acme\ManagementBundle\Entity\User $users)
{
$this->users[] = $users;
return $this;
}
/**
* Remove users
*
* #param \Acme\ManagementBundle\Entity\User $users
*/
public function removeUser(\Acme\ManagementBundle\Entity\User $users)
{
$this->users->removeElement($users);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
public function __toString()
{
return $this->name;
}
/**
* Set product
*
* #param \Acme\GroundStationBundle\Entity\Product $product
* #return Mission
*/
public function setProduct(\Acme\GroundStationBundle\Entity\Product $product = null)
{
$this->product = $product;
return $this;
}
/**
* Get product
*
* #return \Acme\GroundStationBundle\Entity\Product
*/
public function getProduct()
{
return $this->product;
}
}
Please take a look at my changes to your code.
When you define One(product)ToMany(missions) relation you have situation like this:
1. Product has many missions and must have an ArrayCollection of missions which you can add, remove or get all.
class Product
{
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", mappedBy="product")
*/
// RENAME this attribute to plural. Product HAS MANY missions
// Than naming convention is "human readable" addMission and removeMission from collection but getMissions
protected $missions;
//...
//
// remove those functions:
public function setMission($mission)
//...
public function getMission()
//...
//
// add those functions:
public function __construct(){
$this->missions = new ArrayCollection();
}
public function addMission( Acme\ManagementBundle\Entity\Mission $mission )
{
$this->missions[] = $mission;
return $this;
}
public function removeMission( Acme\ManagementBundle\Entity\Mission $mission )
{
$this->missions->removeElement( $mission );
return $this;
}
public function getMissions()
{
return $this->missions;
}
//...
2. Many MissionS are owned by one product. Change only annotation
class Mission {
//...
// RENAME inversedBy to missions
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\ManyToOne(targetEntity="Acme\GroundStationBundle\Entity\Product", inversedBy="missions")
* #ORM\JoinColumn(name="productId", referencedColumnName= "id")
*/
private $product;
EDIT START
3. Opposite - MANY products Belongs to one Mission
If there is situation like you mentioned in comment, then your Annotations are wrong. Look at this fix:
class Product
{
// ...
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\ManyToOne(targetEntity="Acme\GroundStationBundle\Entity\Mission", inversedBy="products")
* #ORM\JoinColumn(name="missionId", referencedColumnName= "id")
*/
protected $mission;
// ...
// roll back this functions:
public function setMission($mission)
public function getMission()
// remove those functions
public function __construct(){
public function addMission( Acme\ManagementBundle\Entity\Mission $mission )
public function removeMission( Acme\ManagementBundle\Entity\Mission $mission )
public function getMissions()
//...
class Mission {
// ...
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="Acme\ManagementBundle\Entity\Product", mappedBy="mission")
*/
private $products;
// ...
//
// remove those functions:
public function setProduct($product)
public function getProduct()
//...
//
// add those functions:
public function __construct(){
$this->products = new ArrayCollection();
}
public function addProduct( Acme\ManagementBundle\Entity\Product $product )
{
$this->products[] = $product;
return $this;
}
public function removeProduct( Acme\ManagementBundle\Entity\Product $product )
{
$this->products->removeElement( $product );
return $this;
}
public function geProducts()
{
return $this->products;
}
//...
EDIT END
3. After that remember to:
$ php app/console doctrine:generate:entities AcmeGroundStationBundle:Product
$ php app/console doctrine:generate:entities AcmeGroundStationBundle:Mission
$ php app/console doctrine:schema:update --force
Good Luck!
By saying this:
Neither the property "missions" nor one of the methods
"getMissions()", "isMissions()", "hasMissions()", "__get()" exist and
have public access in class
"Acme\GroundStationBundle\Entity\Product".
Symfony2 is telling you that you have to set a relationship between Mission and Product entities.
Try to create a oneToMany/manyToOne relationship between those entities by setting up annotations and properties in your objects. I'm not proficient enough in annotations, but I can tell what it would look like in Yaml:
# in Product:
oneToMany:
missions:
targetEntity: Mission
mappedBy: product
# in Mission:
manyToOne:
product:
targetEntity: Product
inversedBy: missions
joinColumn:
name: productId
referencedColumnName: id
Before you test, don't forget to update your objects to your annotations:
$ php app/console doctrine:generate:entities YourBundle:Product
$ php app/console doctrine:generate:entities YourBundle:Mission
Then, tell us what happens in the commentaries. You're gonna have to do some testing before you get it working, in my opinion, but you're on the way ;)