I have a big understanding problem with OneToMany Relationship - i searched a lot but that didnt help, maybe someone can help me with this.
I have a Event Entity with OneToMany Relation
<?php
namespace #\#\#;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Turmforum\BookingBundle\Entity\Contact;
/**
* Event
*
* #ORM\Table(name="events")
* #ORM\Entity
*/
class Event
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Contact", mappedBy="event")
*/
protected $event_contacts;
/**
*
*/
public function __construct() {
$this->contacts = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function getContacts() {
return $this->contacts;
}
public function addContact(Contact $contact) {
$this->contacts[] = $contact;
return $this;
}
And have a Contact Entity with ManyToOne Relation
<?php
namespace #\#\#;
use Doctrine\ORM\Mapping as ORM;
use Turmforum\BookingBundle\Entity\Event;
/**
* Contact
*
* #ORM\Table(name="contacts")
* #ORM\Entity
*/
class Contact
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Event", inversedBy="event_contacts")
* #ORM\JoinColumn(name="event_id", referencedColumnName="id")
*/
protected $event;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getEvent() {
return $this->event;
}
When i try to save my event details over a form i get the error:
Neither the property "event_id" nor one of the methods "getEventId()",
"eventId()", "isEventId()", "hasEventId()", "__get()" exist and have
public access in class "Turmforum\BookingBundle\Entity\Event".
What am i missing?
Related
in my symfony app, i'm using embedded forms. In my case, an object "CompetenceGroupe" can have multiple objects "CompetenceItem", but an object "CompetenceItem" belongs to only one object "CompetenceGroupe", so the relation is manyToOne.
The form work perfectly, and I have two tables (one for each entity), and it's well saved in the database.
But when I select an CompetenceGroupe object with doctrine in my controller, I have all informations of the object, and he's got an empty "competenceItems" property, so I can't retrieve the childs object (CompetenceItem).
My "CompetenceGroupe" entity :
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="competences_groupes")
*/
class CompetenceGroupe
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id_competence_groupe;
/**
* #var User $user
*
* #ORM\ManyToOne(targetEntity="User", cascade={"persist", "merge"})
* #ORM\JoinColumn(name="id_user", referencedColumnName="id_user", nullable=false)
*/
private $user;
/**
* #ORM\Column(type="string", length=60, nullable=true)
*/
protected $titre;
protected $competence_items;
public function __construct()
{
$this->competence_items = new ArrayCollection();
}
public function getCompetenceItems()
{
return $this->competence_items;
}
/**
* Get idCompetenceGroupe
*
* #return integer
*/
public function getIdCompetenceGroupe()
{
return $this->id_competence_groupe;
}
/**
* Set titre
*
* #param string $titre
*
* #return CompetenceGroupe
*/
public function setTitre($titre)
{
$this->titre = $titre;
return $this;
}
/**
* Get titre
*
* #return string
*/
public function getTitre()
{
return $this->titre;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return CompetenceGroupe
*/
public function setUser(\AppBundle\Entity\User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
public function addItem(CompetenceItem $item)
{
$this->competence_items->add($item);
}
public function removeItem(CompetenceItem $item)
{
// ...
}
/**
* Set competenceItems
*
* #param \AppBundle\Entity\CompetenceItem $competenceItems
*
* #return CompetenceGroupe
*/
public function setCompetenceItems(\AppBundle\Entity\CompetenceItem $competenceItems = null)
{
$this->competence_items = $competenceItems;
return $this;
}
}
And my "CompetenceItem" entity :
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="competences_items")
*/
class CompetenceItem
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id_competence_item;
/**
* #ORM\Column(type="string", length=60, nullable=false)
*/
protected $libelle;
/**
* #var CompetenceNiveau $niveau
*
* #ORM\ManyToOne(targetEntity="CompetenceNiveau", cascade={"persist", "merge"})
* #ORM\JoinColumn(name="id_competence_niveau", referencedColumnName="id_competence_niveau", nullable=true)
*/
private $niveau;
/**
* #var CompetenceGroupe $competence_groupe
*
* #ORM\ManyToOne(targetEntity="CompetenceGroupe", cascade={"persist", "merge"})
* #ORM\JoinColumn(name="id_competence_groupe", referencedColumnName="id_competence_groupe", nullable=false)
*/
private $competence_groupe;
/**
* Get idCompetenceItem
*
* #return integer
*/
public function getIdCompetenceItem()
{
return $this->id_competence_item;
}
/**
* Set libelle
*
* #param string $libelle
*
* #return CompetenceItem
*/
public function setLibelle($libelle)
{
$this->libelle = $libelle;
return $this;
}
/**
* Get libelle
*
* #return string
*/
public function getLibelle()
{
return $this->libelle;
}
/**
* Set niveau
*
* #param \AppBundle\Entity\CompetenceNiveau $niveau
*
* #return CompetenceItem
*/
public function setNiveau(\AppBundle\Entity\CompetenceNiveau $niveau = null)
{
$this->niveau = $niveau;
return $this;
}
/**
* Get niveau
*
* #return \AppBundle\Entity\CompetenceNiveau
*/
public function getNiveau()
{
return $this->niveau;
}
/**
* Set competenceGroupe
*
* #param \AppBundle\Entity\CompetenceGroupe $competenceGroupe
*
* #return CompetenceItem
*/
public function setCompetenceGroupe(\AppBundle\Entity\CompetenceGroupe $competenceGroupe)
{
$this->competence_groupe = $competenceGroupe;
return $this;
}
/**
* Get competenceGroupe
*
* #return \AppBundle\Entity\CompetenceGroupe
*/
public function getCompetenceGroupe()
{
return $this->competence_groupe;
}
}
I think I have a missing annotation of the "competence_items" property in the CompetenceGroupe entity, but i'm really not sure ...
Thanks for your help !
A good practice may be to have a competence form, which would be call inside your competence group form
You may add a CollectionType as parrent and include query to search which competence already exist
There are some good example with post form type in symfony demo blog
Or you can use form events (onSubmit, preSubmit, etc...) to charge your entity with your required competence. This example show a message form which allow to choose friend from preset data, this is a good example.
You have tow choice , even to create a Many-To-One, Unidirectional , in this case , you need clean some code , take a look:
In CompetenceGroupe class :
class CompetenceGroupe
{
/**
* Many competence have One Group.
* #ManyToOne(targetEntity="CompetenceItem")
* #JoinColumn(name="id_competence_item", referencedColumnName="id_competence_item")
*/
protected $competence_items;
public function __construct()
{
// $this->competence_items = new ArrayCollection();
//delete that line
}
In CompetenceItem class :
class CompetenceItem
{
You need to delete private $competence_groupe; attribute with his annotation :
By this way, when you dump a CompetenceGroupe object you gonna find the competence items.
Also, you can do it with One-To-Many, Bidirectional ,if you want to get the data from the inverse side and from the owning side .
EDIT: If one competenceGroupe can have many competenceItems, then that is a OneToMany relationship; this is the inverse side of the relationship as defined by doctrine, but that is ok. Your question asked how to pull a competenceGroupe and retrieve all related competenceItems. You can do this by making the competenceItems an ArrayCollection in your CompetenceGroupe entity, just as you have done. You do have to define that further in the annotation, see (updated) code below.
For an ArrayCollection, you can remove your method setCompetenceItems and instead define a method addCompetenceItem in your CompetenceGroupe entity.
class CompetenceGroupe
{
/**
* #ORM\OneToMany(targetEntity="CompetenceItem", mappedBy="competence_groupe")
*/
protected $competenceItems;
public function __construct()
{
$this->competenceItems= new ArrayCollection();
}
/**
* Add competenceItem
*
* #param CompetenceItem $competenceItem
* #return CompetenceGroupe
*/
public function addCompetenceItem(CompetenceItem $competenceItem)
{
$this->competence_items->add($competenceItem);
return $this;
}
}
You'll also need to define the owning side to make all this work.
So this is my code on my newly created page inside the Entity folder...
use Doctrine\ORM\Mapping as ORM;
use Application\Entity\Categories;
use PerfectWeb\Core\Interfaces\Routable;
use Application\Mapper\Injector;
use PerfectWeb\Core\Traits;
use PerfectWeb\Core\View\Helper\Object;
use PerfectWeb\Core\Utils\Slug;
/**
* #ORM\Entity
*/
class VodCategory extends Categories implements
Entity\Interfaces\Categories, Routable
{
function getRoute($type = Object::ROUTE_TYPE_VIEW)
{
return 'category/categories';
}
function getRouteParams()
{
return
[
Injector::CATEGORY => $this->getID(),
'slug' => Slug::getSlug($this->getSlug()),
];
}
}
And this is my category.php file:
<?php
namespace Application\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use PerfectWeb\Core\Traits;
/**
* Categories
* #ORM\Table(name="categories")
* #ORM\Entity
*/
class Categories
{
use Traits\Entity;
use Traits\User;
use Traits\Name;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", nullable=false, unique=false)
*/
protected $name;
/**
* #ORM\ManyToOne(targetEntity="Categories", cascade={"persist"})
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
* #var integer
*/
protected $parent = null;
/**
* #var \Application\Entity\User
*
* #ORM\ManyToOne(targetEntity="User", inversedBy="categories")
* #ORM\JoinColumn(name="user", referencedColumnName="id", onDelete="CASCADE")
*/
protected $user;
/**
*
* #ORM\OneToMany(targetEntity="Videos\Entity\Video", mappedBy="category", fetch="EXTRA_LAZY"))
*
*/
protected $videos;
/**
* #var string
*
* #ORM\Column(name="entity", type="string", nullable=true, unique=false)
*/
protected $entity;
/**
*
* construct function for array collection
*/
public function __construct()
{
$this->videos = new ArrayCollection();
}
/**
* #return mixed
*/
public function getVideos()
{
return $this->videos;
}
/**
* #param mixed $videos
*/
public function setVideos($videos)
{
$this->videos = $videos;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Get parent
*
* #return integer
*/
public function getParent()
{
return $this->parent;
}
/**
* Set parent
*
* #param integer $parent
* #return Categories
*/
public function setParent($parent)
{
$this->parent = $parent;
return $this;
}
public function __toString()
{
return $this->getName();
}
}
the first bit of code gives me an error:
Fatal Error Interface 'Categories\Entity\Interfaces\Categories' not found in /var/www/html/camclients/module/Videos/src/Videos/Entity/VodCategory.php
What am I doing wrong?
You implement the interface Entity\Interfaces\Categories inside your category class but this interface cannot be found.
You should have an interface in that namespace (and folder) or you should point to the correct location (the folder/namespace where your interface is located).
If your interface exists then it is probably a namespace issue like #doydoy44 suggested in the comment. Then make sure that the namespace declaration and file location of your interface are correct.
I have a doubt w.r.t Embedded Forms. I have a "Properties" entity which has 2 fields "id" and "name" and "Amenities" entity which has 2 fields "id" and "value"(id=1,value=wifi,id=2,value=water,id=3,value=food).I have created these 2 entities,but now I want to save the id of "Properties" and "Amenities" into a separate 3rd table.So, I have created a third entity "Properties_Amenities" and its table "properties_amenities".I have created a "one to many" relationship as shown below.I want to embed "Amenities" into "Properties" with the click of an "Add Amenities" button on the "Properties Form".I am not sure as to where to place the "addAmenities()" and "removeAmenities()" functions in the Entity files. Below are 3 entities:-
Properties.php
<?php
namespace EpitaEvents\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Properties
*
* #ORM\Table(name="properties")
* #ORM\Entity
*/
class Properties
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="Properties_Amenities", mappedBy="properties",cascade={"persist"})
**/
private $properties_amenities1;
public function __construct() {
$this->properties_amenities1 = new ArrayCollection();
}
/**
* Get id
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*/
public function getName()
{
return $this->name;
}
/**
* Get properties_amenities1
*/
public function getProperties_Amenities1()
{
return $this->properties_amenities1;
}
/**
* Set properties_amenities1
*
*/
public function setProperties_Amenities1($properties_amenities1)
{
$this->properties_amenities1 = $properties_amenities1;
return $this;
}
/**
* Add Amenities
*
* #return Properties
*/
public function addAmenities(\EpitaEvents\FormBundle\Entity\Properties_Amenities $amenities)
{
$amenities->setProperties($this);
$this->amenities[] = $amenities;
return $this;
}
/**
* Remove Amenities
*
*/
public function removeAmenities(\EpitaEvents\FormBundle\Entity\Properties_Amenities $amenities) {
$this->amenities->removeElement($amenities);
}
}
Amenities.php
<?php
namespace EpitaEvents\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Amenities
*
* #ORM\Table(name="amenities")
* #ORM\Entity
*/
class Amenities
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="value", type="string", length=100)
*/
private $value;
/**
* #ORM\OneToMany(targetEntity="Properties_Amenities", mappedBy="amenities")
**/
private $properties_amenities2;
public function __construct() {
$this->properties_amenities2 = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set value
*
* #param string $value
* #return Amenities
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Get value
*
* #return string
*/
public function getValue()
{
return $this->value;
}
/**
* Set Properties
*
*/
public function setProperties_Amenities2($properties_amenities2)
{
$this->properties_amenities2 = $properties_amenities2;
return $this;
}
/**
* Get Properties
*
* #return EpitaEvents\FormBundle\Entity\Properties
*/
public function getProperties_Amenities2()
{
return $this->properties_amenities2;
}
}
(Also should the __construct() be put in these 2 above files or in "Properties_Amenities.php"(Below)???)
Properties_Amenities.php
<?php
namespace EpitaEvents\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Properties_Amenities
*
* #ORM\Table(name="properties_amenities")
* #ORM\Entity
*/
class Properties_Amenities
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Properties", inversedBy="properties_amenities1")
* #ORM\JoinColumn(name="properties_id", referencedColumnName="id")
**/
private $properties;
/**
* #ORM\ManyToOne(targetEntity="Amenities", inversedBy="properties_amenities2")
* #ORM\JoinColumn(name="amenities_id", referencedColumnName="id")
**/
private $amenities;
function getId() {
return $this->id;
}
function getProperties() {
return $this->properties;
}
function getAmenities() {
return $this->amenities;
}
function setProperties($properties) {
$this->properties = $properties;
}
function setAmenities($amenities) {
$this->amenities = $amenities;
}
}
Can any one suggest as to where to place the "addAmenities()" and "removeAmenities()" functions as I want to save the "id's" of "Properties.php" and "Amenities.php" in a "SEPARATE, THIRD" Entity and table??
I have a many to one relation between my entities.
An application can have activities
<?php
namespace AppAcademic\ApplicationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Activity
*
* #ORM\Table()
* #ORM\Entity
*/
class Activity
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="AppAcademic\ApplicationBundle\Entity\Application", inversedBy="activity")
* #ORM\JoinColumn(name="application_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $application;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function setApplication($application)
{
$this->application = $application;
return $this;
}
public function getApplication()
{
return $this->application;
}
/**
* Set title
*
* #param string $title
* #return Activity
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
And the application
/**
* Application
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppAcademic\ApplicationBundle\Entity\ApplicationRepository")
*/
class Application
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="AppAcademic\ApplicationBundle\Entity\Activity", mappedBy="application")
*/
protected $activities;
...
}
I have this in the profiler:
AppAcademic\ApplicationBundle\Entity\Application
The mappings AppAcademic\ApplicationBundle\Entity\Application#activities and AppAcademic\ApplicationBundle\Entity\Activity#application are inconsistent with each other.
AppAcademic\ApplicationBundle\Entity\Application
The mappings AppAcademic\ApplicationBundle\Entity\Application#activities and AppAcademic\ApplicationBundle\Entity\Activity#application are inconsistent with each other.
AppAcademic\ApplicationBundle\Entity\Activity
The association AppAcademic\ApplicationBundle\Entity\Activity#application refers to the inverse side field AppAcademic\ApplicationBundle\Entity\Application#activity which does not exist.
For the mapping annotation ManyToOne on the Activity::$application property, the attribute
inversedBy="activity"
This should be
inversedBy="activities"
I'm trying to create the database tables using Symfony command's using the following line :
php app/console doctrine:schema:create
I obtain the following error :
[Doctrine\ORM\Mapping\MappingException]
No identifier/primary key specified for Entity "Cupon\CiudadBundle\Entity\Ciudad". Every Entity must have an identifier/primary key.
And it's the above class :
namespace Cupon\TiendaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity */
class Tienda
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/** #ORM\ManyToOne(targetEntity="Cupon\CiudadBundle\Entity\Ciudad") */
protected $ciudad;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set ciudad
*
* #param \Cupon\CiudadBundle\Entity\Ciudad $ciudad
* #return Tienda
*/
public function setCiudad(\Cupon\CiudadBundle\Entity\Ciudad $ciudad = null)
{
$this->ciudad = $ciudad;
return $this;
}
/**
* Get ciudad
*
* #return \Cupon\CiudadBundle\Entity\Ciudad
*/
public function getCiudad()
{
return $this->ciudad;
}
public function __toString()
{
return $this->getNombre();
}
}
I don't understand whats really happen, because I put the ID for the class. Any help is appreciated.
Just check if the Ciudad Entity has an id
You should include the following annotations for example:
namespace Cupon\TiendaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity */
class Ciudad
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
//..