I have the following two classes which are have a ManyToMany relationship and saved in a joining table called countries_involved.
class CountriesInvolved
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $description;
/**
* #var \DateTime
*/
private $createdAt;
/**
* #var \DateTime
*/
private $updatedAt;
/**
* #var \ACME\SouthBundle\Entity\Country
*/
private $country;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $involvement;
}
and
class Involvement
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $description;
}
The relationship is defined as below in YML
manyToMany:
involvement:
targetEntity: Involvement
joinTable:
name: countries_involvement
joinColumns:
case_country_involved_id:
referencedColumnName: id
inverseJoinColumns:
involvement_id:
referencedColumnName: id
I'm trying to return results of countries involved based on the id of an involvement but kind of stuck in writing the query without getting an error. Here's what I tried thus far:
$em = $this->getDoctrine()->getManager()->createQueryBuilder();
$q = $em->select('c')
->from('ACMESouthBundle:CountriesInvolved','c')
->innerJOIN('c.Involvement','i')
->where('i.id = 1')
->groupBy('c.country')->getQuery();
The error is:
[Semantical Error] line 0, col 80 near 'i WHERE i.id': Error: Class ACME\SouthBundle\Entity\CountriesInvolved has no association named Involvement
Firstly, I would recommend the use of annotations, your code will be more readable.
The problem I think is that you have forgotten inversedBy and mappedBy properties.
The following code is a possible solution to your problem using annotations.
You should add this code to Involvement entity:
/**
* #ORM\ManyToMany(targetEntity="CountriesInvolved", inversedBy="involvement")
* #ORM\JoinTable(name="countries_involvement",
* joinColumns={#ORM\JoinColumn(name="case_country_involved_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="involvement_id", referencedColumnName="id")}
* )
*/
private $countries;
and in CountriesInvolved entity you should add the following annotations in $involvement:
/**
* #ORM\ManyToMany(targetEntity="Involvement", mappedBy="countries")
*/
private $involvement;
I have just rewrite the query, something like this:
$em = $this->getEntityManager();
$query = $em->createQuery('
SELECT c
FROM ACMESouthBundle:CountriesInvolved c
JOIN c.involvement i
WHERE i.id = :id
');
$query->setParameter('id', '1');
return $query->getResult();
EDIT
This is with YAML method:
CountriesInvolved:
manyToMany:
involvement:
targetEntity: Involvement
mappedBy: countries
CountriesInvolved:
manyToMany:
countries:
targetEntity: CountriesInvolved
inversedBy: involvement
joinTable:
name: countries_involvement
joinColumns:
case_country_involved_id:
referencedColumnName: id
inverseJoinColumns:
involvement_id:
referencedColumnName: id
Related
I have a manyToMany relation beetween "Lot" and "BailProprietaire"
When i get an entity "BailProprietaire", i see the entities "lot" linked
But when i get an entity "Lot", i don't see entities "BailProprietaire" linked
In lot.orm.yml, i have :
AppBundle\Entity\Lot:
type: entity
repositoryClass: AppBundle\Repository\LotRepository
table: lot
....
....
manyToMany:
bauxProprietaire:
targetEntity: BailProprietaire
mappedBy: lots
In bailProprietaire.orm.yml, i have :
AppBundle\Entity\BailProprietaire:
type: entity
table: bail_proprietaire
repositoryClass: AppBundle\Repository\BailProprietaireRepository
....
....
manyToMany:
lots:
targetEntity: Lot
inversedBy: bauxProprietaire
fetch: LAZY
joinTable:
name: bail_proprietaire_lots
joinColumns:
bail_id:
referencedColumnName: id
inverseJoinColumns:
lot_id:
referencedColumnName: id
lifecycleCallbacks: { }
do you see something i miss ?
thanks
EDIT : Add php entity code
Lot.php
class Lot
{
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $bauxProprietaire;
/**
* Constructor
*/
public function __construct()
{
$this->bauxProprietaire = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add bauxProprietaire
*
* #param \AppBundle\Entity\BailProprietaire $bauxProprietaire
*
* #return Lot
*/
public function addBauxProprietaire(\AppBundle\Entity\BailProprietaire $bauxProprietaire)
{
$this->bauxProprietaire[] = $bauxProprietaire;
return $this;
}
/**
* Remove bauxProprietaire
*
* #param \AppBundle\Entity\BailProprietaire $bauxProprietaire
*/
public function removeBauxProprietaire(\AppBundle\Entity\BailProprietaire $bauxProprietaire)
{
$this->bauxProprietaire->removeElement($bauxProprietaire);
}
/**
* Get bauxProprietaire
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBauxProprietaire()
{
return $this->bauxProprietaire;
}
}
BailProprietaire.php
class BailProprietaire
{
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $lots;
/**
* Constructor
*/
public function __construct()
{
$this->lots = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add lot
*
* #param \AppBundle\Entity\Lot $lot
*
* #return BailProprietaire
*/
public function addLot(\AppBundle\Entity\Lot $lot)
{
$this->lots[] = $lot;
return $this;
}
/**
* Remove lot
*
* #param \AppBundle\Entity\Lot $lot
*/
public function removeLot(\AppBundle\Entity\Lot $lot)
{
$this->lots->removeElement($lot);
}
/**
* Get lots
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getLots()
{
return $this->lots;
}
}
EDIT 2 : in fact, it works but not with the listener
in fact i see the entities "BailProprietaire" when i get a "lot" but when i flush data, i have a listener. In this listener, i call a virtual propertie of "Lot.php" where i have :
if (!empty($this->bauxProprietaire)) {
....
} else {
....
}
but $this->bauxProprietaire is always empty
Ok, i found the problem.
When i do $this->bauxProprietaire, i have a "Doctrine\ORM\PersistentCollection" but when i look the collection in this object, there is 0 element
but if i do $this->bauxProprietaire->toArray(), i see my relation
I don't understand why but it works
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 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 am trying to create a symfony2 application. The main idea behind the project is that there is an event which many guests are invited to and they are categorized. I have created a relational model for all the entities.
There are 4 tables:
Guests - who is invited
Category - what category/categories he belongs to ?
Event - the event which they are invited to
Guest_Event (attendance)
I have concluded to the following schemas:
xxxxBundle\Entity\Guest:
type: entity
table: guest
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 100
nullable: false
surname:
type: string
length: 100
nullable: false
email:
type: string
length: 255
nullable: true
address:
type: string
length: 255
nullable: true
phone:
type: string
length: 10
description:
type: text
created_at:
type: datetime
updated_at:
type: datetime
nullable: true
token:
type: string
length: 255
unique: true
is_activated:
type: boolean
nullable: true
manyToOne:
category:
targetEntity: Category
inversedBy: guest
joinColumn:
name: category_id
referencedColumnName: id
lifecycleCallbacks:
prePersist: [ setCreatedAtValue ]
preUpdate: [ setUpdatedAtValue ]
Category
xxxxBundle\Entity\Category:
type: entity
table: category
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 255
unique: true
oneToMany:
guests:
targetEntity: Guest
mappedBy: category
attend:
targetEntity: Attendance
mappedBy: category
Event
xxxxxBundle\Entity\Event:
type: entity
table: event
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 100
nullable: false
location:
type: string
length: 255
nullable: true
scheduled_at:
type: datetime
manyToMany:
category:
targetEntity: guest
inversedBy: event
joinColumn:
name: event_id
referencedColumnName: id
A guest might belong to multiple categories (manyToOne)
A category will have many guests (manyToOne)
A guest might attend many events (manyToOne)
An event might have many attendants (manyToMany?)
the attendance table (guest_event) should be a join table ?
I am a little bit confused about ORM and doctrine coding. Creating the tables via SQL code or phpmyadmin seems much easier to me but I want to go the hard way ! The documentation seems confusing because each tutorial suggests different things and the doctrine ORM section in the symfony2 book doesn't have a complete example but pieces of code..
How can I correct my tables to include all the specifications ?
My two cents:
A guest might belong to multiple categories
So many guests can belong to many categories, so it's many to many guest side. Assuming the owning side is Guest:
xxxxBundle\Entity\Guest:
manyToMany:
categories:
targetEntity: Category
inversedBy: guests
joinTable:
name: guests_categories
A category will have many guests (manyToOne)
If category will have many guests, why is's many to one? Many categories can be assigned to many guest:
xxxxBundle\Entity\Category:
manyToMany:
guests:
targetEntity: Guest
mappedBy: categories
If i understand you correctly, a categoy may exist even without a guest, and vice-versa a guest may exist even without a category.
And for guest/events relation, i'll go again for many to many / many to many. Take a look at here and ask yourself: one/many type of my entity can have one/many type of another entity?
I would strongly suggest you work your way through the official Symfony 2 documentation:
http://symfony.com/doc/master/book/doctrine.html
It takes you step by step through the process of initializing the database, making an entity, mapping it to the database and then using the entity.
You are trying to understand multiple concepts by reading assorted documentation. The fact that you seem to have yaml files in your entity directory indicates a basic lack of understanding.
Go through the tutorial first then add in your real entities. It's pretty straight forward once you get a few things working.
I changed my mind and used annotations as yaml seems confusing to me.
So far :
For the Guest entity
<?php
// xxxxBundle/Entity/Guest.php
namespace xxxxBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\MaxLength;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="guest")
*/
class Guest
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ManyToMany(targetEntity="Category", inversedBy="guests")
* #JoinTable(name="guests_categories")
*/
protected $categories;
/**
* #ManyToMany(targetEntity="Event", inversedBy="events")
* #JoinTable(name="guests_events")
*/
protected $events;
/**
* #ORM\Column(type="string", length=30)
*/
protected $name;
/**
* #ORM\Column(type="string", length=30)
*/
protected $surname;
/**
* #ORM\Column(type="string", length=30)
*/
protected $email;
/**
* #ORM\Column(type="string", length=100)
*/
protected $address;
/**
* #ORM\Column(type="string", length=10)
*/
protected $phone;
/**
* #ORM\Column(type="string", length=10)
*/
protected $mobile;
/**
* #ORM\Column(type="text")
*/
protected $description;
/**
* #ORM\Column(type="datetime")
*/
protected $created_at;
/**
* #ORM\Column(type="datetime")
*/
protected $updated_at;
/**
* #ORM\Column(type="string")
*/
protected $token;
/**
* #ORM\Column(type="boolean")
*/
protected $is_activated;
public function __construct() {
$this->categories = new \Doctrine\Common\Collections\ArrayCollection();
}
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('name', new NotBlank());
$metadata->addPropertyConstraint('surname', new NotBlank());
$metadata->addPropertyConstraint('email', new Email(array(
'message' => 'I do not like invalid emails. Give me a real one!')));
$metadata->addPropertyConstraint('phone', new MaxLength(10));
$metadata->addPropertyConstraint('mobile', new MaxLength(10));
}
}
For the Category entity
<?php
// xxxxBundle/Entity/Category.php
namespace xxxxBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\MaxLength;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="category")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ManyToMany(targetEntity="Guest", mappedBy="categories")
*/
protected $guests;
/**
* #ORM\Column(type="string", length=30)
*/
protected $name;
/**
* #ORM\Column(type="text")
*/
protected $description;
public function __construct() {
$this->categories = new \Doctrine\Common\Collections\ArrayCollection();
}
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('name', new NotBlank());
}
}
For the Event entity
<?php
// xxxxBundle/Entity/Event.php
namespace xxxxBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\MaxLength;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="event")
*/
class Event
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ManyToMany(targetEntity="Guest", mappedBy="categories")
*/
protected $guests;
/**
* #ORM\Column(type="string", length=30)
*/
protected $name;
/**
* #ORM\Column(type="string", length=100)
*/
protected $location;
/**
* #ORM\Column(type="text")
*/
protected $description;
/**
* #ORM\Column(type="datetime")
*/
protected $scheduled_at;
public function __construct() {
$this->categories = new \Doctrine\Common\Collections\ArrayCollection();
}
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('name', new NotBlank());
$metadata->addPropertyConstraint('location', new NotBlank());
}
}
I feel confused about the Attendance entity. The Attendance entity will have the following variables:
Guest_id
Event_id
Will_attend (yes/no/maybe)
Comment
Replied_at
Updated_at
I do not know which will be the primary key (or the primary keys?). The db table does not need to have a separate Id (or not?).
<?php
// xxxxBundle/Entity/Attendance.php
namespace xxxxBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="attendance")
*/
class Attendance
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ManyToMany(targetEntity="Guest", mappedBy="categories")
*/
protected $guests;
/**
* #ManyToMany(targetEntity="Event", mappedBy="events")
*/
protected $events;
/**
* #ORM\Column(type="string", length=3)
*/
protected $will_attend;
/**
* #ORM\Column(type="text")
*/
protected $description;
/**
* #ORM\Column(type="datetime")
*/
protected $replied_at;
public function __construct() {
$this->categories = new \Doctrine\Common\Collections\ArrayCollection();
}
}
The attendance entity requires a person to declare while he/she will attend an event or not. That means that it's a oneToOne relation because for every event must be ONE event - ONE person - ONE attendance reply.
The solution is to change the following code in the attendance entity :
/**
* #ORM\OneToOne(targetEntity="Guest")
*/
protected $guests;
/**
* #ORM\OneToOne(targetEntity="Event")
*/
protected $events;
Then run php app/console doctrine:generate:entities , php app/console doctrine:schema:update --force and the crud command If you generate them automatically. Now everything works fine.
I'm trying to apply Doctrine to an existing database that has a OneToMany relationship between two tables: Commerce and Area.
I generated the yml schema from the database resulting in the following:
Area:
type: entity
table: area
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
name:
type: string
length: 255
fixed: false
nullable: true
lifecycleCallbacks: { }
Commerce:
type: entity
table: commerce
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
name:
type: string
length: 255
fixed: false
nullable: true
manyToOne:
area:
targetEntity: Area
cascade: { }
mappedBy: null
inversedBy: null
joinColumns:
area_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
From that schema I generated the Entities:
use Doctrine\ORM\Mapping as ORM;
/**
* Model\EntitiesBundle\Entity\Area
*
* #ORM\Table(name="area")
* #ORM\Entity
*/
class Area
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #return string
*/
public function getName()
{
return $this->name;
}
}
use Doctrine\ORM\Mapping as ORM;
/**
* Model\EntitiesBundle\Entity\Commerce
*
* #ORM\Table(name="commerce")
* #ORM\Entity
*/
class Commerce
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var Area
*
* #ORM\ManyToOne(targetEntity="Area")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="area_id", referencedColumnName="id")
* })
*/
private $area;
/**
* #return \Model\EntitiesBundle\Entity\Area
*/
public function getArea()
{
return $this->area;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
}
My problem comes when I try:
$commerce = $em->getRepository('ModelEntitiesBundle:Commerces')
->find($id);
echo $commerce->getArea()->getName();
The Area entity has empty attributes.
Any ideas? Thank you!
I solved the problem. It was somewhere else, I have two Entity Managers and the one I needed was not the default.