for some reason whenever i use php app/console doctrine:schema:update --dump-sql it gives me this error:
[ReflectionException]
Property sava\UserBundle\Entity\User::$Tickets does not exist
usually i first create the orm and then generate with doctrine:generate:entities, my problem is whenever im trying to update the schema, it gives me this error, i have already tried:
clear doctrine cache with php app/console doctrine:cache:clear-query, clear mapping, ect.
manually deleting the cache folder.
deleting ticket entity and generating them again.
setting all the fields to protected.
i ran out of ideas.
error this are my dependencys.
User.Orm:
sava\UserBundle\Entity\User:
type: entity
table: User
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
nombreCliente:
type: string
length: 200
fixed: false
nullable: false
column: nombre_cliente
rifCedula:
type: string
length: 40
fixed: false
nullable: false
column: rif_cedula
telefono:
type: string
length: 30
fixed: false
nullable: true
celular:
type: string
length: 30
fixed: false
nullable: true
direccion:
type: string
length: 250
fixed: false
nullable: true
oneToMany:
Tickets:
targetEntity: sava\SoporteBundle\Entity\TblTicket
mappedBy: idUser
cascade: ["persist", "remove"]
lifecycleCallbacks: { }
Ticket.Orm.
sava\SoporteBundle\Entity\TblTicket:
type: entity
table: tbl_ticket
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
titulo:
type: string
length: '80'
contenido:
type: text
isClosed:
type: boolean
fecha:
type: date
oneToMany:
respuestas:
targetEntity: sava\SoporteBundle\Entity\TblRespuesta
mappedBy: ticket
cascade: ["persist", "remove"]
oneToOne:
idUser:
targetEntity: sava\UserBundle\Entity\User
inversedBy: Tickets
#nullable: true
joinColumn:
name: id_user
referencedColumnName: id
lifecycleCallbacks: { }
Ticket entity(deleted some unrelated fields for clarity):
<?php
namespace sava\SoporteBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TblTicket
*/
class TblTicket
{
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
public function __construct()
{
$this->respuestas = new \Doctrine\Common\Collections\ArrayCollection();
}
protected $idUser;
public function setIdUser(\sava\UserBundle\Entity\User $idUser = null)
{
$this->idUser = $idUser;
return $this;
}
/**
* Get idUser
*
* #return \sava\UserBundle\Entity\User
*/
public function getIdUser()
{
return $this->idUser;
}
}
>
this is my ticket entity extended by fos/user/bundle (some fields where deleted for clarity):
namespace sava\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
/**
* user
*
*/
class User extends BaseUser
{
public function __construct()
{
parent::__construct();
//$this->User = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
protected $Tickets;
/**
* Add Tickets
*
* #param \sava\SoporteBundle\Entity\TblTicket $tickets
* #return User
*/
public function addTicket(\sava\SoporteBundle\Entity\TblTicket $tickets)
{
$this->Tickets[] = $tickets;
return $this;
}
/**
* Remove Tickets
*
* #param \sava\SoporteBundle\Entity\TblTicket $tickets
*/
public function removeTicket(\sava\SoporteBundle\Entity\TblTicket $tickets)
{
$this->Tickets->removeElement($tickets);
}
/**
* Get Tickets
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTickets()
{
return $this->Tickets;
}
}
nevermind, an old bundle where i was testing the userbundle had an entity that somehow was being targeted by doctrine. deleted the old bundle and its working fine.
if you ever have this problem check your bundles for extra unwanted entities or the namespaces.
You have to update your entity first:
php app/console doctrine:generate:entities [YourBundle:YouEntity]
Related
I have a User entity with a self-referencing one-to-many relationship - Every User owns a set of students (who are also users):
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*/
class User extends BaseUser
{
/**
* #var int
*/
protected $id;
private $students;
// ....
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
public function __construct() {
$this->students = new ArrayCollection();
// ...
parent::__construct();
}
/**
* Remove student
*
* #return User
*/
public function removeStudent($student)
{
$this->students->removeElement($student);
return $this;
}
/**
* Add a student
*
* #param User $students
*
* #return User
*/
public function addStudent($student)
{
$this->students->add($student);
return $this;
}
/**
* Get students
*
* #return User
*/
public function getStudents()
{
$this->students;
}
/**
* Set students
*
* #param User $students
*
* #return User
*/
public function setStudents($students)
{
$this->students = $students;
return $this;
}
// ....
}
The mapping is done as a one-to-many unidirectional with join table
AppBundle\Entity\User:
type: entity
table: null
repositoryClass: AppBundle\Repository\UserRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
// ...
manyToMany:
students:
targetEntity: User
joinTable:
name: mentors_students
joinColumns:
mentor_id:
referencedColumnName: id
inverseJoinColumns:
student_id:
referencedColumnName: id
unique: true
lifecycleCallbacks: { }
Now when I add/edit a user using the EasyAdmin bundle, I can add the students for that user. However, when I retrieve the entity, the students property is always null. For example, when I view the list of users:
Here the user 'sagarl3232' is supposed to be a student of 'sj' but the view above clearly shows the property when retrieved is null.
The entity is persisted correctly in the database. That is, the join table has the right values:
Why is Doctrine doing this to me? Isn't it supposed to hydrate the students array automatically?
Your getter doesnt return anything!
/**
* Get students
*
* #return User[]
*/
public function getStudents()
{
return $this->students;
}
BTW why you should adjust the docblock too. The getter is supposed to return an array User[]
i Have a single page application and i use symfony as a Rest API.
In my object "ResidenceIntervenant, i have a ManyToOne relation :
manyToOne:
intervenant:
targetEntity: Intervenant
cascade: { }
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
intervenant_id:
referencedColumnName: id
orphanRemoval: false
When i do this :
$myData = json_decode($request->getContent(), true);
$intervenant = $this->em->getRepository('AppBundle:Intervenant')->find($intervenantId);
$relation = new ResidenceIntervenant();
$myData['intervenant'] = $intervenant->getId();
$form_relation = $this->formFactory->create(ResidenceIntervenantType::class, $relation, ['method' => "POST"]);
$form_relation->submit($myData, TRUE);
if ( ! $form_relation->isValid()) {
$this->em->persist($relation);
$this->em->flush();
}
it works and i have the id in my table
When i do :
$myData = json_decode($request->getContent(), true);
$intervenant = $this->em->getRepository('AppBundle:Intervenant')->find($intervenantId);
$relation = new ResidenceIntervenant();
$relation->setIntervenant($intervenant);
$form_relation = $this->formFactory->create(ResidenceIntervenantType::class, $relation, ['method' => "POST"]);
$form_relation->submit($myData, TRUE);
if ( ! $form_relation->isValid()) {
$this->em->persist($relation);
$this->em->flush();
}
it doesn't persists the id
Is this normal ?
my FormType biuldForm method :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('contratNum')
->add('appareilNum')
->add('intervenantOrigine')
->add('intervenant')
->add('residence');
}
Thanks for your help
EDIT : add informations to show my entities
I tried to add these linee but it neither works:
$intervenant->addResidenceIntervenant($relation);
$this->em->persist($intervenant);
$this->em->flush();
ResidenceIntervenant Entity :
<?php
namespace AppBundle\Entity;
/**
* ResidenceIntervenant
*/
class ResidenceIntervenant
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $contratNum;
/**
* #var string
*/
private $appareilNum;
/**
* #var boolean
*/
private $intervenantOrigine;
/**
* #var \AppBundle\Entity\Intervenant
*/
private $intervenant;
/**
* #var \AppBundle\Entity\Residence
*/
private $residence;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set contratNum
*
* #param string $contratNum
*
* #return ResidenceIntervenant
*/
public function setContratNum($contratNum)
{
$this->contratNum = $contratNum;
return $this;
}
/**
* Get contratNum
*
* #return string
*/
public function getContratNum()
{
return $this->contratNum;
}
/**
* Set appareilNum
*
* #param string $appareilNum
*
* #return ResidenceIntervenant
*/
public function setAppareilNum($appareilNum)
{
$this->appareilNum = $appareilNum;
return $this;
}
/**
* Get appareilNum
*
* #return string
*/
public function getAppareilNum()
{
return $this->appareilNum;
}
/**
* Set intervenantOrigine
*
* #param boolean $intervenantOrigine
*
* #return ResidenceIntervenant
*/
public function setIntervenantOrigine($intervenantOrigine)
{
$this->intervenantOrigine = $intervenantOrigine;
return $this;
}
/**
* Get intervenantOrigine
*
* #return boolean
*/
public function getIntervenantOrigine()
{
return $this->intervenantOrigine;
}
/**
* Set intervenant
*
* #param \AppBundle\Entity\Intervenant $intervenant
*
* #return ResidenceIntervenant
*/
public function setIntervenant(\AppBundle\Entity\Intervenant $intervenant = null)
{
$this->intervenant = $intervenant;
return $this;
}
/**
* Get intervenant
*
* #return \AppBundle\Entity\Intervenant
*/
public function getIntervenant()
{
return $this->intervenant;
}
/**
* Set residence
*
* #param \AppBundle\Entity\Residence $residence
*
* #return ResidenceIntervenant
*/
public function setResidence(\AppBundle\Entity\Residence $residence = null)
{
$this->residence = $residence;
return $this;
}
/**
* Get residence
*
* #return \AppBundle\Entity\Residence
*/
public function getResidence()
{
return $this->residence;
}
}
ResidenceIntervenant.orm.yml
AppBundle\Entity\ResidenceIntervenant:
type: entity
table: residence_intervenant
indexes:
fk_residence_intervenant_interv_id_idx:
columns:
- intervenant_id
fk_residence_intervenant_res_id_idx:
columns:
- residence_id
id:
id:
type: integer
nullable: false
options:
unsigned: false
id: true
generator:
strategy: IDENTITY
fields:
contratNum:
type: string
nullable: true
length: 100
options:
fixed: false
column: contrat_num
appareilNum:
type: string
nullable: true
length: 100
options:
fixed: false
column: appareil_num
intervenantOrigine:
type: boolean
nullable: false
options:
default: false
column: intervenant_origine
manyToOne:
intervenant:
targetEntity: Intervenant
cascade: ["persist"]
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
intervenant_id:
referencedColumnName: id
orphanRemoval: false
residence:
targetEntity: Residence
cascade: { }
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
residence_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
Intervenant Entity :
<?php
namespace AppBundle\Entity;
/**
* Intervenant
*/
class Intervenant
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $libelleContact;
/**
* #var string
*/
private $url;
/**
* #var \AppBundle\Entity\Metier
*/
private $metier;
/**
* #var \AppBundle\Entity\Tiers
*/
private $tiers;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set libelleContact
*
* #param string $libelleContact
*
* #return Intervenant
*/
public function setLibelleContact($libelleContact)
{
$this->libelleContact = $libelleContact;
return $this;
}
/**
* Get libelleContact
*
* #return string
*/
public function getLibelleContact()
{
return $this->libelleContact;
}
/**
* Set url
*
* #param string $url
*
* #return Intervenant
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* Get url
*
* #return string
*/
public function getUrl()
{
return $this->url;
}
/**
* Set metier
*
* #param \AppBundle\Entity\Metier $metier
*
* #return Intervenant
*/
public function setMetier(\AppBundle\Entity\Metier $metier = null)
{
$this->metier = $metier;
return $this;
}
/**
* Get metier
*
* #return \AppBundle\Entity\Metier
*/
public function getMetier()
{
return $this->metier;
}
/**
* Set tiers
*
* #param \AppBundle\Entity\Tiers $tiers
*
* #return Intervenant
*/
public function setTiers(\AppBundle\Entity\Tiers $tiers = null)
{
$this->tiers = $tiers;
return $this;
}
/**
* Get tiers
*
* #return \AppBundle\Entity\Tiers
*/
public function getTiers()
{
return $this->tiers;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $residenceIntervenant;
/**
* Constructor
*/
public function __construct()
{
$this->residenceIntervenant = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add residenceIntervenant
*
* #param \AppBundle\Entity\ResidenceIntervenant $residenceIntervenant
*
* #return Intervenant
*/
public function addResidenceIntervenant(\AppBundle\Entity\ResidenceIntervenant $residenceIntervenant)
{
$this->residenceIntervenant[] = $residenceIntervenant;
return $this;
}
/**
* Remove residenceIntervenant
*
* #param \AppBundle\Entity\ResidenceIntervenant $residenceIntervenant
*/
public function removeResidenceIntervenant(\AppBundle\Entity\ResidenceIntervenant $residenceIntervenant)
{
$this->residenceIntervenant->removeElement($residenceIntervenant);
}
/**
* Get residenceIntervenant
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getResidenceIntervenant()
{
return $this->residenceIntervenant;
}
}
Intervenant.orm.yml :
AppBundle\Entity\Intervenant:
type: entity
table: intervenant
indexes:
fk_intervenant_metier_id_idx:
columns:
- metier_id
fk_intervenant_tiers_id_idx:
columns:
- tiers_id
id:
id:
type: integer
nullable: false
options:
unsigned: false
id: true
generator:
strategy: IDENTITY
fields:
libelleContact:
type: string
nullable: false
length: 255
options:
fixed: false
column: libelle_contact
url:
type: string
nullable: true
length: 255
options:
fixed: false
oneToMany:
residenceIntervenant:
targetEntity: ResidenceIntervenant
mappedBy: intervenant
cascade: [remove]
oneToOne:
tiers:
targetEntity: Tiers
joinColumn:
name: tiers_id
referencedColumnName: id
cascade: [remove, persist]
manyToOne:
metier:
targetEntity: Metier
cascade: ["persist"]
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
metier_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
EDIT : Problem solved
i updated addResidenceIntervenant like this :
public function addResidenceIntervenant(\AppBundle\Entity\ResidenceIntervenant $residenceIntervenant)
{
$this->residenceIntervenant[] = $residenceIntervenant;
$residenceIntervenant->setIntervenant($this);
return $this;
}
i added these lines after persisting my relation :
$intervenant->addResidenceIntervenant($relation);
$this->em->persist($intervenant);
Your second example has this line:
$relation->setIntervenant($intervenant);
Does the method setIntervenant() set the relation?
I think you should do something like this:
public function setIntervenant(Intervenant $intervenant)
{
$this->intervenant = $intervenant;
$intervenant->setResidence($this);
}
Anyway, the relations in Doctrine can be unidirectional or bidirectional.
Your Many-To-One relation seems to be unidirectional. You should set a One-To-Many relation on your Intervenant entity.
Read more about this in the Doctrine documentation:
Many-to-One, Unidirectional (This is what you did)
One-to-Many, bidirectional (This is what you should do)
One-To-Many, Unidirectional with Join Table (Just for completeness)
So, you should trait your Intervenant as the Doctrine treats the Feature while your ResidenceIntervenant has to be treated as the Product in the Doctrine documentation.
I have a strange problem using a many-to-many relation in Symfony (with Doctrine), I've never had before in symfony projects with many-to-many relations and I can't find any difference to the other projects.
I have the two entitys Product and Tag and a many-to-many relation to each other. Unfortunately, if I try to add a product to a tag or vice versa, the error
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "TestBundle\Entity\Product#$tags", got "TestBundle\Entity\Tag" instead.
appears.
The code used to add a tag to a product:
$tag1 = $em->getRepository('TestBundle:Tag')->findOneBy(array(
'tag' => "Bla"
));
$tag1->addProduct($product);
$em->persist($tag1);
$em->persist($product);
$em->flush();
Of course, the variable $tag1 and $product both contain a valid entity.
The YAML file for the many-to-many relations (I cut away irrelevant parts):
TestBundle\Entity\Tag:
type: entity
table: tags
repositoryClass: TestBundle\Repository\TagRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
tag:
type: string
length: 255
unique: true
manyToMany:
products:
targetEntity: Product
mappedBy: tags
lifecycleCallbacks: { }
Product:
TestBundle\Entity\Product:
type: entity
table: products
repositoryClass: TestBundle\Repository\ProductRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 255
unique: true
manyToOne:
manufacturer:
targetEntity: Manufacturer
inversedBy: products
joinColumn:
name: manufacturer_id
referencedColumnName: id
onDelete: CASCADE
manyToMany:
tags:
targetEntity: Product
inversedBy: products
joinTable:
name: tags2products
joinColumns:
tag_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
lifecycleCallbacks: { }
The setter and getter functions also don't contain any special tricks:
The Tag.php entity file contains:
/**
* Constructor
*/
public function __construct()
{
$this->product = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add product
*
* #param \TestBundle\Entity\Product $product
*
* #return Tag
*/
public function addProduct(\TestBundle\Entity\Product $product)
{
$product->addTag($this);
$this->product[] = $product;
return $this;
}
public function removeProduct(\TestBundle\Entity\Product $product)
{
$this->product->removeElement($product);
}
/**
* Get products
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
While the Product.php contains:
/**
* Add tag
*
* #param \TestBundle\Entity\Tag $tag
*
* #return Product
*/
public function addTag(Tag $tag)
{
$this->tags->add($tag);
//$this->tags[] = $tag;
return $this;
}
/**
* Remove tag
*
* #param \TestBundle\Entity\Tag $webpage
*/
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tag) ;
}
/**
* Get webpages
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
return $this->tags;
}
I also tried to add a $this->tags = new ArrayCollection(); to the constructor of the product, but it didnt change anything.
Also, there is no problem adding, reading and persisting tags to products. The error is thrown as soon as I call $em->flush().
Does anybody know why my Product entity expects a array collection? I never told him to expect one! Thank you very much in advance!
The error is telling you that the property "#tags" of the entity TestBundle\Entity\Product that you are trying to flush, contains an object of type TestBundle\Entity\Tag instead of a collection of this object. Doctrine expects this collection/array because the metadata for that property states that TestBundle\Entity\Product is in a many-yo-many with TestBundle\Entity\Tag and the relation is done via the property "#tags". This should happen if:
//You did this
$this->tags = $tag;
//instead of what you actually did which is correct
$this->tags->add($tag);
//Or
$this->tags[] = $tag;
But the code that you posted here should not produce that exception.
Are you sure there is no other place where an accessor method is called that changes the tags property of TestBundle\Entity\Product? Something like and event listener?
I finally found out what the strange problem was. Thank you Alexandr Cosoi for confirming the way I tried to add my entity.
The Problem was a configuration error I didn't notice.
manyToMany:
tags:
targetEntity: Product
inversedBy: products
joinTable:
name: tags2products
joinColumns:
tag_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
targetEntity was set to Product but it had to be set to "Tag". Changing it just solved my problem as expected. :)
I have a problem related to Doctrine2:
1- I have two tables joining on a many-to-one relation:
Table 1 - Activity
The Schema:
Backend\adminBundle\Entity\Activity:
type: entity
table: activity
indexes:
result_id:
columns:
- result_id
id:
id:
type: integer
nullable: false
unsigned: false
comment: ''
id: true
generator:
strategy: IDENTITY
fields:
......
manyToOne:
result:
targetEntity: Actionresult
cascade: { }
mappedBy: null
inversedBy: null
joinColumns:
result_id:
referencedColumnName: id
orphanRemoval: false
The Entity
<?php
namespace Backend\adminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Activity {
/**
* #var \Backend\adminBundle\Entity\Actionresult
*
* #ORM\ManyToOne(targetEntity="Backend\adminBundle\Entity\Actionresult")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="result_id", referencedColumnName="id")
* })
*/
private $result;
/**
* #var \Backend\adminBundle\Entity\SfGuardUser
*
* #ORM\ManyToOne(targetEntity="Backend\adminBundle\Entity\SfGuardUser")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
/* There are other Properties */
/**
* Set result
*
* #param \Backend\adminBundle\Entity\Actionresult $result
* #return Activity
*/
public function setResult(\Backend\adminBundle\Entity\Actionresult $result = null)
{
$this->result = $result;
return $this;
}
/**
* Get result
*
* #return \Backend\adminBundle\Entity\Actionresult
*/
public function getResult()
{
return $this->result;
}
}
Table 2 - Actionresult Related to Activity Table by Id:
The schema:
Backend\adminBundle\Entity\Actionresult:
type: entity
table: actionresult
id:
id:
type: integer
nullable: false
unsigned: false
comment: ''
id: true
generator:
strategy: IDENTITY
fields:
name:
type: string
nullable: false
length: 255
fixed: false
comment: ''
lifecycleCallbacks: { }
The Entity:
<?php
namespace Backend\adminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Actionresult
*
* #ORM\Table(name="actionresult")
* #ORM\Entity
*/
class Actionresult
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Actionresult
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
The Question:
With doctrine i can refer from table Activity to Actionresult with the name result.
How can i refer with doctrine from table Actionresult to Activity??
Thank you in advance.
To be thorough, you should try and stick to one type of entity mapping in Symfony whenever possible. The #ORM* annotations are redundant if you use YAML config, and vice-versa. I'll provide the answer using YAML, and I believe you'll be able to convert to annotations if need be.
# Activity.yml
Activity:
type: entity
...
manyToOne:
result:
targetEntity: ActionResult
inversedBy: activities
# ActionResult.yml
Result:
type: entity
oneToMany:
activities:
targetEntity: Activity
mappedBy: result
# ActionResult.php
class Result {
protected $activities;
public function __construct()
{
$this->activities = new Doctrine\Common\Collections\ArrayCollection();
}
public function getActivities()
{
return $this->activities;
}
public function addActivity(Activity $activity)
{
$activity->setResult($this);
$this->activities->add($activity);
}
public function removeActivity(Activity $activity)
{
$activity->setResult(null);
$this->activities->removeElement($activity);
}
}
# Activity.php
class Activity {
protected $result;
public function getResult()
{
return $this->result;
}
public function setResult(ActionResult $result = null)
{
$this->result = $result;
}
}
Reference:
Bidirectional one to many: http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#one-to-many-bidirectional
I follow the docs from here http://symfony.com/doc/current/book/doctrine.html
and I have a issue.
I created a relation between the category and the product model. The database has been updated correctly, model classes have right getters and setters, but if I try to run following code:
$product = $this->getDoctrine()->getRepository('AcmeStoreBundle:Product')
->findById(1);
$categoryName = $product->getCategory()->getName();
I gets an error:
FatalErrorException: Error: Call to a member function getName() on a
non-object in
D:\www\Symfony\src\Acme\StoreBundle\Controller\DefaultController.php
line 28
I checked it out and the category model class has getName() method and it is a public method.
My Product.orm.yml looks like
Acme\StoreBundle\Entity\Product:
type: entity
manyToOne:
category:
targetEntity: Category
inversedBy: products
joinColumn:
name: category_id
referencedColumnName: id
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: 255
price:
type: decimal
lifecycleCallbacks: { }
Category.orm.yml
Acme\StoreBundle\Entity\Category:
type: entity
oneToMany:
products:
targetEntity: Product
mappedBy: category
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: '255'
lifecycleCallbacks: { }
Product.php
...
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
...
Category.php
...
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
protected $products;
public function __construct() {
$this->products = new ArrayCollection();
}
...
What's the problem?
You are retrieving a $category instead of a $product in your sample code.
$product = $this->getDoctrine()->getManager()->getRepository('AcmeStoreBundle:Product')->findOneById(1);
$categoryName = $product->getCategory()->getName();
note that you forgot the getManager()
Edit : You need to use findOneById() instead of findById. The first method will return only one single result (your object), the findBy* will return you an array of results on which you can't call getCategory() without traversing it inside a loop.