Array Collection: The mapping association are incosistent with each other - php

I have an User entity and a mission entity, that are associated
In the profiler of symfony i get two errors.
For the class Acme\ManagementBundle\Entity\User I get:
The mappings Acme\ManagementBundle\Entity\User#missions and Acme\ManagementBundle\Entity\Mission#users are incosistent with each other.
For the class Acme\ManagementBundle\Entity\Mission I get:
The association Acme\ManagementBundle\Entity\Mission#users refers to the inverse side field Acme\ManagementBundle\Entity\User#users which does not exist.
I tried to solve by myself reading here but I could't.
My mission entity is:
class Mission {
/**
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\User", inversedBy="users")
*/
protected $users;
public function __construct(){
$this -> users = new ArrayCollection();
}
/**
* 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;
}
//...
}
And my user entity:
abstract class User extends BaseUser
{
/**
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", mappedBy="users")
*/
protected $missions;
public function __construct(){
parent::__construct();
$this -> missions = new ArrayCollection();
}
/**
* Add missions
*
* #param \Acme\ManagementBundle\Entity\Mission $missions
* #return User
*/
public function addMission(\Acme\ManagementBundle\Entity\Mission $missions)
{
$this->missions[] = $missions;
return $this;
}
/**
* Remove missions
*
* #param \Acme\ManagementBundle\Entity\Mission $missions
*/
public function removeMission(\Acme\ManagementBundle\Entity\Mission $missions)
{
$this->missions->removeElement($missions);
}
/**
* Get missions
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMission()
{
return $this->missions;
}
}

You have wrong annotation in the users property in Mission class. It should be:
/**
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\User", inversedBy="missions")
*/
protected $users;

Related

Add fields for Sonata UserBundle

I have a question about extending Sonata UserBundle entity. I need to add more fields to the entity.
Firstly, I extended Sonata UserBundle to my project on the folder src\Application\Sonata\UserBundle
Then I tried to add these fields on the User Entity available on the same folder:
<?php
namespace App\Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* #link https://sonata-project.org/easy-extends
*
* References:
* #link http://www.doctrine-project.org/projects/orm/2.0/docs/reference/working-with-objects/en
*/
class User extends BaseUser
{
/**
* #var int $id
*/
protected $id;
/**
* Get id.
*
* #return int $id
*/
public function getId()
{
return $this->id;
}
/**
* #var string
* #ORM\Column(type="string")
*/
protected $accountType;
/**
* #var int
* #ORM\ManyToOne(targetEntity="App\Entity\Specialty")
*/
protected $specialty;
/**
* Get AccountType
* #return string
*/
public function getAccountType()
{
return $this->accountType;
}
/**
* Set AccountType
* #param string $accountType
* #return $this
*/
public function setAccountType($accountType)
{
$this->accountType = $accountType;
return $this;
}
/**
* Get Specialty
* #return int
*/
public function getSpecialty()
{
return $this->specialty;
}
/**
* Set Specialty
* #param int $specialty
* #return Specialty
*/
public function setSpecialty($specialty)
{
$this->specialty = $specialty;
return $this;
}
}
On the fos_user.yml I mapped this entity. But when I try to update my schema, by running this command:
php bin/console doctrine:s:u --force
I have a message that states that Nothing to update - your database is already in sync with the current entity metadata.
The added field isn't added on my table. I'm not an expert on Symfony, so I tried to explain my situation as possible as I can.
Specialty entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="specialties")
* #ORM\Entity
*/
class Specialty
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Icon")
*/
private $icon;
/**
* #ORM\Column(type="boolean")
*/
private $status;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
/**
* Get string
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set name
* #param string $name
* #return Specialty
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* #return mixed
*/
public function getIcon()
{
return $this->icon;
}
/**
* #param mixed $icon
* #return $this
*/
public function setIcon($icon)
{
$this->icon = $icon;
return $this;
}
public function getStatus()
{
return $this->status;
}
public function setStatus($status)
{
$this->status = $status;
return $this;
}
public function __toString()
{
return $this->getId() ? (string) $this->getName() : '-';
}
}
Did you run php bin/console make:migration after adjusting the Entity?
php bin/console make:entity (create or update the Entity)
If you prefer to add new properties manually, the make:entity command can generate the getter & setter methods for you: php bin/console make:entity --regenerate
php bin/console make:migration
inspect src/Migrations/ folder
run the migrations php bin/console doctrine:migrations:migrate
read

Doctrine2 / querying discriminator value

For a project, I need to manage "cards".
There are 2 card types : "Client card" and "Member card".
Cards can be ordered by a user of this application.
To achieve that, I created an abstract Card entity using a Type discriminator.
/* #ORM\Entity
* #ORM\Table(name="cards")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"member"="MemberCard", "client"="ClientCard"})
*/
abstract class Card
{
const MEMBER = 'member';
const CLIENT = 'client';
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="CardsOrder", inversedBy="cards")
* #ORM\JoinColumn(name="order_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $order;
/**
* Return the card type
*
* #return string
*/
abstract public function getType();
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param CardsOrder $order
*
* #return $this
*/
public function setOrder(CardsOrder $order)
{
$this->order = $order;
return $this;
}
/**
* #return CardsOrder
*/
public function getOrder()
{
return $this->order;
}
}
The MemberCard entity
/**
* #ORM\Entity
*/
class MemberCard extends Card
{
/**
* #ORM\ManyToOne(targetEntity="Member", inversedBy="cards")
* #ORM\JoinColumn(name="member_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $member;
/**
* #param Member $member
*
* #return $this
*/
public function setMember(Member $member)
{
$this->member = $member;
return $this;
}
/**
* #return Member
*/
public function getMember()
{
return $this->member;
}
/**
* #return string
*/
public function getType()
{
return self::MEMBER;
}
}
The ClientCard entity
/**
* #ORM\Entity
*/
class ClientCard extends Card
{
/**
* ClientCard - client n-1 relation
*
* #ORM\ManyToOne(targetEntity="Client", inversedBy="cards")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $client;
/**
* #param \Admin\Crm\Entity\Client\Client $client
*
* #return $this
*/
public function setClient(Client $client)
{
$this->client = $client;
return $this;
}
/**
* #return Client
*/
public function getClient()
{
return $this->client;
}
/**
* #return string
*/
public function getType()
{
return self::CLIENT;
}
}
Now, I want to know if a member or a client has a pending ordered card (status is a binary status flag) :
public function findPendingCard($clientOrMember)
{
// $this->getRepository is the Card repository, injected in a factory
$query = $this->getRepository()->createQueryBuilder('c')
->join('c.order', 'o', 'WITH', 'BIT_AND(o.status, :oStatus) > 0')
->where('c INSTANCE OF :memberCardEntity AND c.member = :clientOrMember')
->orWhere('c INSTANCE OF :clientCardEntity AND c.client = :clientOrMember')
->setParameters([
'oStatus' => CardsOrder::OPEN,
'clientOrMember' => $clientOrMember,
'memberCardEntity' => MemberCard::class,
'clientCardEntity' => ClientCard::class,
])
->getQuery();
return $query->getOneOrNullResult();
}
But I got this error :
[Semantical Error] line 0, col 148 near 'member = :clientOrMember)': Error: Class Card has no field or association named member
Any idea what I'm doing wrong?
It's not so much that you're doing something wrong, but there is a method to work around the issue. You can make it possible to return the card type with the following.
In class Card add:
public function getCardType()
{
return $this->discr;
}
in class MemberCard add:
protected $discr = 'member';
in class ClientCard add:
protected $discr = 'client';

Doctrine + Zend Framework 2: Insert array of data in a many to many relationship

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.

Doctrine & Symfony2 join multiple tables

I've been struggling with doing a multiple join in DQL.
Here is my code:
$query = $em->createQuery(
'SELECT k
FROM AppBundle:Keyword k
JOIN k.company c
JOIN k.entry e
WHERE c.user = :id
ORDER BY k.name ASC'
)->setParameter('id',$user_id);
But it gives me "Notice: Undefined index: entry", when executing it.
Here is my keyword entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Keyword
*/
class Keyword
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Keyword
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $user;
/**
* Constructor
*/
public function __construct()
{
$this->user = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add user
*
* #param \AppBundle\Entity\User $user
* #return Keyword
*/
public function addUser(\AppBundle\Entity\User $user)
{
$this->user[] = $user;
return $this;
}
/**
* Remove user
*
* #param \AppBundle\Entity\User $user
*/
public function removeUser(\AppBundle\Entity\User $user)
{
$this->user->removeElement($user);
}
/**
* Get user
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUser()
{
return $this->user;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
* #return Keyword
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $company;
/**
* Add company
*
* #param \AppBundle\Entity\Company $company
* #return Keyword
*/
public function addCompany(\AppBundle\Entity\Company $company)
{
$this->company[] = $company;
return $this;
}
/**
* Remove company
*
* #param \AppBundle\Entity\Company $company
*/
public function removeCompany(\AppBundle\Entity\Company $company)
{
$this->company->removeElement($company);
}
/**
* Get company
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCompany()
{
return $this->company;
}
/**
* Set company
*
* #param \AppBundle\Entity\Company $company
* #return Keyword
*/
public function setCompany(\AppBundle\Entity\Company $company = null)
{
$this->company = $company;
return $this;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $entry;
/**
* Add entry
*
* #param \AppBundle\Entity\Entry $entry
* #return Keyword
*/
public function addEntry(\AppBundle\Entity\Entry $entry)
{
$this->entry[] = $entry;
return $this;
}
/**
* Remove entry
*
* #param \AppBundle\Entity\Entry $entry
*/
public function removeEntry(\AppBundle\Entity\Entry $entry)
{
$this->entry->removeElement($entry);
}
/**
* Get entry
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEntry()
{
return $this->entry;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $ranking;
/**
* Add ranking
*
* #param \AppBundle\Entity\Ranking $ranking
* #return Keyword
*/
public function addRanking(\AppBundle\Entity\Ranking $ranking)
{
$this->ranking[] = $ranking;
return $this;
}
/**
* Remove ranking
*
* #param \AppBundle\Entity\Ranking $ranking
*/
public function removeRanking(\AppBundle\Entity\Ranking $ranking)
{
$this->ranking->removeElement($ranking);
}
/**
* Get ranking
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRanking()
{
return $this->ranking;
}
}
And my entry entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Entry
*/
class Entry
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $path;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set path
*
* #param string $path
* #return Entry
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* #var \AppBundle\Entity\Keyword
*/
private $keyword;
/**
* Set keyword
*
* #param \AppBundle\Entity\Keyword $keyword
* #return Entry
*/
public function setKeyword(\AppBundle\Entity\Keyword $keyword = null)
{
$this->keyword = $keyword;
return $this;
}
/**
* Get keyword
*
* #return \AppBundle\Entity\Keyword
*/
public function getKeyword()
{
return $this->keyword;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $ranking;
/**
* Constructor
*/
public function __construct()
{
$this->ranking = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add ranking
*
* #param \AppBundle\Entity\Ranking $ranking
* #return Entry
*/
public function addRanking(\AppBundle\Entity\Ranking $ranking)
{
$this->ranking[] = $ranking;
return $this;
}
/**
* Remove ranking
*
* #param \AppBundle\Entity\Ranking $ranking
*/
public function removeRanking(\AppBundle\Entity\Ranking $ranking)
{
$this->ranking->removeElement($ranking);
}
/**
* Get ranking
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRanking()
{
return $this->ranking;
}
}
Btw I'm pretty new with symfony and doctrine.
I appreciate all kinds of help!
You need to provide mapping information for each attribute in your model class as well as provide the Entity mapping for the class. Take a look at http://doctrine-common.readthedocs.org/en/latest/reference/annotations.html
Each of your model classes need the #ORM\Entity annotation to tell doctrine it is a mapped entity. So for your case you would have:
/**
* Entry
* #ORM\Entity
*/
class Entry
{
...
Then each attribute you want to be mapped to the database needs an #ORM\Column annotation. For example:
/**
* #var integer
* #ORM\Id #ORM\Column #ORM\GeneratedValue
*/
private $id;
/**
* #var string
* #ORM\Column(type="string")
*/
private $path;
Then you need to create relationship mapping annotations for any relationships between your models (Keyword -> Company, Keyword -> Entry etc), using one of the mappings on here http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html
Once you have all the correct mappings use the command line tool app/console doctrine:schema:update to make sure your model is in sync with your database.
Your DQL seems fine so once you have the correct mappings in place you might have better luck.

ArrayCollection: retrieve collection in a form

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 ;)

Categories