have a element class with composite keys.
When I run php app/console doctrine:schema:validate
I get the following error
The join columns of the association 'parentElement' have to match to
ALL identifier columns of the target entity
'AgRecord\AppBundle\Entity\Element', however 'id, parent_uuid' are
missing.
What am I missing or how do I correctly describe the relationship?
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* Elements
*
* #ORM\Table(name="elements",uniqueConstraints={#ORM\UniqueConstraint(name="search_idx", columns={"uuid", "id", "parent_uuid"})})
* #ORM\Entity
*/
class Element
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", columnDefinition="INT AUTO_INCREMENT UNIQUE")
* #ORM\Id
*/
private $id;
/**
* #var guid
* #ORM\Id
* #ORM\Column(name="uuid", type="string", unique=true, nullable=false)
*/
private $uuid;
/**
* #var guid
* #ORM\Id
* #ORM\Column(name="parent_uuid", type="string")
*/
private $parentUUID;
/**
* #ORM\ManyToOne(targetEntity="Element", inversedBy="childElements")
* #ORM\JoinColumn(name="uuid", referencedColumnName="parent_uuid")
*/
private $parentElement;
/**
* #ORM\Id
* #ORM\OneToMany(targetEntity="Element", mappedBy="parentElement")
* #ORM\JoinColumn(name="uuid", referencedColumnName="element_uuid")
*/
private $childElements;
}
I was stupid I had all the mappings mixed up...
I solved my issue kind of.
First I decided to just remove id and have uuid, which meant i didnt need a composite key.
Then needed to remove stupidly placed #Id off of all non primary fields
Then removed the $parentUUID.
I was doing it the wrong way and didn't understand the mapping, and using an extra reference when it wasn't needed.
Then removed the joined annotation from the child elements and made sure to have the inversedby correctly set on the parent.
The name on the parent join annotation needs to be the name of the class member associated.
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* Elements
*
* #ORM\Table(name="elements")
* #ORM\Entity
*/
class Element
{
private $id;
/**
* #var guid
* #ORM\Id
* #ORM\Column(name="uuid", type="string", unique=true, nullable=false)
*/
private $uuid;
/**
* #ORM\ManyToOne(targetEntity="Element", inversedBy="childElements")
* #ORM\JoinColumn(name="parentElement", referencedColumnName="uuid")
*/
private $parentElement;
/**
* #ORM\OneToMany(targetEntity="Element", mappedBy="parentElement")
*/
private $childElements;
}
Related
I'm trying to get a legacy database into the doctrine mappings.
All the tables have a combined primary key. One ID and one "optios id".
The problem is that Optios ID always has to be set but the OneToOne relation with the same columns causes the column "Optios ID" to be set to null. I'm not sure what I'm doing wrong or is there a way around it?
PS: The 'Pack' relation is optional.
<?php
namespace CalendarBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="CalendarBundle\Repository\CategoryRepository")
* #ORM\Table(name="Categories")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="Category_id")
*/
private $id;
/**
* #ORM\Column(type="integer", name="Optios_id")
* #ORM\Id
*/
private $optiosId;
/**
* #ORM\Column(type="string", name="Name")
*/
private $name;
/**
* #ORM\Column(type="boolean", name="AvailableOnline")
*/
private $online;
/**
* #ORM\Column(type="integer", name="SequenceNumber", nullable=true)
*/
private $order;
/**
* #ORM\Column(type="integer", name="Parent_id")
*/
private $parentId;
/**
* One Category has Many Packs.
*
* #var Pack
*
* #ORM\OneToOne(targetEntity="Pack", inversedBy="category")
* #ORM\JoinColumns(
* #ORM\JoinColumn(name="Pack_id", referencedColumnName="Pack_id"),
* #ORM\JoinColumn(name="Optios_id", referencedColumnName="Optios_id"),
* )
*/
private $pack;
/**
* #ORM\Column(type="boolean", name="Deleted")
*/
private $deleted;
I keep getting the error in the title when I want to login using the FOSUserBundle on Symfony. The problem is, I already have an "id" for my User table from my database so I don't want to create an "id" field like they ask on the FOSUserBundle guide. I don't understand why it would give me this error when there is no more "id" field in my code.
Is this "id" field mandatory?
Here is the code of my User class (here called "Utilisateurs")`use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
/**
* Utilisateurs
*
* #ORM\Table(name="utilisateurs", indexes={#ORM\Index(name="FK_UTILISATEURS_id_sexe", columns={"id_sexe"}), #ORM\Index(name="FK_UTILISATEURS_id_niveau", columns={"id_niveau"})})
* #ORM\Entity
*/
class Utilisateurs extends BaseUser
{
public function __construct()
{
parent::__construct();
}
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=25, nullable=true)
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="prenom", type="string", length=25, nullable=true)
*/
private $prenom;
/**
* #var \DateTime
*
* #ORM\Column(name="date_naissance", type="date", nullable=true)
*/
private $dateNaissance;
/**
* #var string
*
* #ORM\Column(name="url_photo", type="string", length=100, nullable=true)
*/
private $urlPhoto;
/**
* #var integer
*
* #ORM\Column(name="id_utilisateur", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idUtilisateur;
/**
* #var \Site\UserBundle\Entity\Sexes
*
* #ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\Sexes")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_sexe", referencedColumnName="id_sexe")
* })
*/
private $idSexe;
/**
* #var \Site\UserBundle\Entity\Niveaux
*
* #ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\Niveaux")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_niveau", referencedColumnName="id_niveau")
* })
*/
private $idNiveau;`
As you can see I already have an "id_utilisateur" field which is the id of this entity.
And here is the code of the entity information in XML: The XML Code
Also here is a screenshot of the error I get when I try to log in: The Error
I think the problem is that per convention the id field is often called just id and in some places FOS UserBundle is expecting exactly that, e.g. in the UserProvider.
There are a few ways you can get around this. For instance you could just write your own UserProvder (using the one linked above as a reference) where you substitute the id with your field. You might have to do this in other places as well.
The easier solution would be to just change your entity to something like this:
/**
* #var integer
*
* #ORM\Column(name="id_utilisateur", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
public function getId() { return $this->id; }
Similarly in xml this would look like this:
<id name="id" column="id_utilisateur" type="integer">
<generator strategy="IDENTITY" />
</id>
This way in your entity you will use the expected property and accessor method, but in the background it will map to the database field id_utilisateur, so you you don't have to make any changes to your database.
This should already solve your problems. When a new user is generated Doctrine will take map $user->getId() to user_table.id_utilisateur automatically. If your existing code is making use of the old get-method you could just keep it around and mark it as deprecated:
/**
* #deprecated Use getId() instead.
*/
public function getIdUtilisateur()
{
return $this->getId();
}
I'm using a third party software which neither using Symfony nor Doctrine nor something else. Only PHP & MySQL.
And now I tried to generate entities from this old MySQL structure and using them into my project.
But I don't understand this double primary key situation.
I should split the parameter in explicit field and bind them separately... But in the doctrine documentation it seems possible, too. So what they want? http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#use-case-2-simple-derived-identity
/** #Id #OneToOne(targetEntity="User") */
This is the error message I get.
[Doctrine\ORM\ORMInvalidArgumentException]
Binding an entity with a composite primary key to a query is not supported.
You should split the parameter into the explicit fields and bind them separately.
And this is my first entity:
src/ShMaBundle/Entity/Passage.php
<?php
// src/ShMaBundle/Entity/Passage.php
namespace ShMaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Passage
*
* #ORM\Table(name="passage", #ORM\Index(name="IDX_98AF07F7EC91F2AA", columns={"DcplID"})})
* #ORM\Entity
*/
class Passage
{
/**
* #var boolean
*
* #ORM\Column(name="PositionsIdx", type="boolean", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $positionsidx;
/**
* #var Discipline
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\OneToOne(targetEntity="Discipline")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="DcplID", referencedColumnName="DcplID")
* })
*/
private $dcplid;
}
And this is my second entity.
src/ShMaBundle/Entity/Discipline.php
<?php
// src/ShMaBundle/Entity/Discipline.php
namespace ShMaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Discipline
*
* #ORM\Table(name="discipline")
* #ORM\Entity
*/
class Discipline
{
/**
* #var integer
*
* #ORM\Column(name="DcplID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $dcplid;
}
And year I don't know why doctrine can't load the entity and ignoring everything else. I can access the id by $passage->dcplid->dcplid. Or they want that I do it more better. Having something like this.
<?php
// src/ShMaBundle/Entity/Passage.php
namespace ShMaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Passage
*
* #ORM\Table(name="passage", #ORM\Index(name="IDX_98AF07F7EC91F2AA", columns={"DcplID"})})
* #ORM\Entity
*/
class Passage
{
/**
* #var boolean
*
* #ORM\Column(name="PositionsIdx", type="boolean", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $positionsidx;
/**
* #var integer
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $dcplid;
/**
* #var Discipline
*
* #ORM\OneToOne(targetEntity="Discipline")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="DcplID", referencedColumnName="DcplID")
* })
*/
private $dcpl;
}
Then I can access the discipline and the id separately.
But if I test this then I have an empty dcplid. But the $dcpl works and is filled. Hmm...
If it's possible, merge the oneToOne tables into one single table.
You should also use better attribute names like :
/**
* Passage
*
* #ORM\Table(name="passage", #ORM\Index(name="IDX_98AF07F7EC91F2AA", columns={"DcplID"})})
* #ORM\Entity
*/
class Passage
{
/**
* #var boolean
*
* #ORM\Column(name="PositionsIdx", type="boolean", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $positionsidx;
/**
* #var Discipline
*
* #ORM\OneToOne(targetEntity="Discipline")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="DcplID", referencedColumnName="DcplID")
* })
*/
private $discipline;
public function getDiscipline(){
return $this->discipline;
}
}
When do you have this error, on a query ?
Why don't you have any getter and setter methods ?
You should use a getter : $passage->getDiscipline()
Then, you can access the Id of the discipline
EDIT :
In the class Passage :
You have to remove the following :
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
that is over the attribute :
private $dcplid
I just started working with symfony and doctrine. I have a simple entity which has one property is not tied with the database. This property should contain the contents of the xml file (I wanna make xml file, when doctrine add rows to the database).
/**
* Layouts
*
* #ORM\Table(name="layouts")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
*/
class Layouts
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="layouts_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* ???????
*/
private $template_body;
...
}
How to describe $template_body property? Without leaving the property description, I ran into a problem - the doctrine does not cause preUpdate method when I edit this property in the form.
You can do that my simply flagging a PreUpdate method in your class, which in turn begins working on your $template_body variable.
Please change
* #ORM\HasLifecycleCallbacks()
to
* #ORM\HasLifecycleCallbacks
and create a function like so..
/**
* #PreUpdate
*/
public function myUpdateFunction()
{
// Do stuff
}
I am trying to remove comments from a parent entity, I remember doing this on my last website but now it's not working..
My entity - users
namespace Application\Entities;
use Doctrine\ORM\Mapping AS ORM,
Doctrine\Common\Collections\ArrayCollection;
/**
* Loan
*
* #ORM\Table(name="users")
* #ORM\Entity
*/
class Users{
/**
* #var integer $id
*
* #ORM\Column(type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $username
*
* #ORM\Column(type="string", length=45, nullable=false)
*/
private $username;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Comments", mappedBy="author", cascade={"persist", "remove"})
*/
private $comments;
public function getComments(){
return $this->comments;
}
and my comments table:
namespace Application\Entities;
use Doctrine\ORM\Mapping AS ORM,
Doctrine\Common\Collections\ArrayCollection;
/**
* Loan
*
* #ORM\Table(name="comments")
* #ORM\Entity
*/
class Comments{
/**
* #var integer $id
*
* #ORM\Column(type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer $user_id
*
* #ORM\Column(type="integer", length=15, nullable=false)
*/
private $user_id
/**
* #var Loan
*
* #ORM\ManyToOne(targetEntity="Users", inversedBy="comments",cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $author;
This is fine, it works and I get all collections called comments in the users repository..
Now, I usually do this when I need to delete:
$commentToDelete = $this->em->getRepository('Entities\Comments')->findOneById(375);
$userResults = $this->em->getRepository('Entities\Users')->findOneById(23);
$userResults->getComments()->removeElement($commentToDelete);
$this->em->flush();
Nothing deletes, neither it throws an exception to tell me it hasn't.
I doctrine flushed it too, checked the db, and it's still there..
UPDATE:
Straight after I removeElement, I looped through the user id = 23 dataset, and the comment data for id375 is not there... so it removed it from the collection but not from the DB, and I thought $em->flush() is supposed to do this?
Please advise
Thanks
You need to use
$em->remove($commentToDelete);
$em->flush();
Because the mapping is held in the comment you need to remove this entity to remove the reference before you flush which will save the state to the db.