I always get an exception with my entities. I tried to play with them. I checked on google which relation is the most appropriate for my entities... But I couldn't find the best configuration.
I'm making a website where you can create some albums.
A user can have multiple albums.So I have an entity Album and I have inside a user property :
/**
* Album
*
* #ORM\Table(name="album")
* #ORM\Entity(repositoryClass="Moodress\Bundle\AlbumBundle\Entity\AlbumRepository")
*/
class Album
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
** #ORM\ManyToOne(targetEntity="Moodress\Bundle\UserBundle\Entity\User")
** #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="creationDate", type="datetime")
*/
private $creationDate;
/**
* #var \DateTime
*
* #ORM\Column(name="modificationDate", type="datetime")
*/
private $modificationDate;
/**
* #ORM\OneToMany(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Picture", cascade={"persist"}, mappedBy="album")
*/
private $pictures;
/**
* Constructor
*/
public function __construct()
{
$this->creationDate = new \Datetime();
$this->modificationDate = new \Datetime();
}
// Get and set
}
However, When a user subscribe on the website, I create a default album called Upload that I want to keep in the user class.
This is what I tried to do :
/**
* User
*
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToOne(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album", cascade={"persist"})
*/
protected $albumUpload;
// Get and set
}
I have this error :
Undefined index: album in /Users/Sandro/sites/moodress-website/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1608. This error appears directly when I serialize any entity that has a user object...
The error is caused by the association annotation of the $albumUpload property in the User class.
Doctrine assumes that you have a $album property in your Album entity when you use a #ORM\OneToOne(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album") association in your User entity.
Try
/**
** #ORM\ManyToOne(targetEntity="Moodress\Bundle\UserBundle\Entity\User", inversedBy="albums")
** #ORM\JoinColumn(nullable=false)
*/
private $user;
in your Album entity and
/**
* #ORM\OneToMany(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album", mappedBy="user", cascade={"persist"})
*/
protected $albums;
in your User entity. In addition please add $this->albums = new ArrayCollection() to User::__construct().
Now if you want to add and keep a default album for users you should implement this somewhere in your business logic. You could figure out a way to identify the default album in your collection of albums and prevent deletion especially for this item.
Hope this helps.
My error:
'Undefined index: album'
results from this annotation in the Album class.
/**
* #ORM\OneToMany(
* targetEntity="Moodress\Bundle\AlbumBundle\Entity\Picture",
* cascade={"persist"},
* mappedBy="album"
* )
*/
I have set mappedBy to album but there is no $album property in my Picture class.
I did add this to my Picture class and clear my cache.
/**
* #ORM\ManyToOne(
* targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album",
* inversedBy="pictures"
* )
*/
protected $album;
It solved my problem
Related
I'm trying to implement a doctrine relation for a symphony 3 app.
I have two different classes, one extending from the other, which are related to the same entity with a many to one relation.
Here are my classes.
Country.php
class Country
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Groups({"exposed"})
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Link", mappedBy="country")
*/
private $link;
/**
* #ORM\OneToMany(targetEntity="LinkChild", mappedBy="country")
*/
private $linkChild;
public function __construct()
{
$this->link = new ArrayCollection();
$this->linkChild = new ArrayCollection();
}
}
Link.php
/**
* Link
*
* #ORM\Table(name="link")
* #ORM\Entity(repositoryClass="Decathlon\AppCollaboratorBundle\Reposito\LinkRepository")
* #Vich\Uploadable
* #ORM\HasLifecycleCallbacks()
*/
class Link
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Serializer\Groups({"link_list", "link_info"})
* #Serializer\Expose()
*/
protected $id;
/**
* #var Country
*
* #ORM\ManyToOne(targetEntity="Country", inversedBy="link", cascade={"persist"})
* #JoinColumn(name="country_id", referencedColumnName="id")
*/
protected $country;
}
LinkChild.php
/**
* #ORM\Entity(repositoryClass="Decathlon\AppCollaboratorBundle\Repository\LinkChildRepository")
*/
class LinkChild extends Link
{
/**
* #var Country
*
* #ORM\ManyToOne(targetEntity="Country", inversedBy="linkChild", cascade={"persist"})
* #JoinColumn(name="country_id", referencedColumnName="id")
*/
protected $country;
}
I need to create a relation between both Link and LinkChild to Country but no country column is created in LinkChild table.
I've told not to use recursive classes so I must create Link and LinkChild.
Is there a way to acomplish what I'm tryng to do.
Thank you in advance.
I think what you are looking for is single table inheritance?
<?php
namespace MyProject\Model;
/**
* #Entity
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* #Entity
*/
class Employee extends Person
{
// ...
}
Take a look here:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#single-table-inheritance
Try renaming your protected $country; variable to something like private $childCountry; to make it a variable that belongs specifically to LinkChild.
Your protected $country; override in LinkChild is ignored because it is exactly the same as the one in Link.
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 have made a queryBuilder inside an entity repository to delete a link between two table.
I have this two entities
Domain :
/**
* #var int
*
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string", length=64)
* #Assert\NotBlank
* #Assert\Length(max="64")
* #AppAssert\DomainName
*/
private $name;
// Some other fields
/**
* #var SshKey[]|ArrayCollection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\SshKey", inversedBy="domains")
* #ORM\JoinTable(name="domain_sshkey",
* joinColumns={#ORM\JoinColumn(referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="key_id", referencedColumnName="id")}
* )
*/
private $sshKeys;
And SshKeys :
/**
* #var int
*
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $createdAt;
// Other fields
/**
* #var Domain[]|ArrayCollection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Domain", mappedBy="sshKeys")
*/
private $domains;
I am trying to delete links between this two tables when SshKeys id is in sshKeys field inside domain table.
So I made this query builder in my DomainRepository
public function deleteSshkeyDomainLink($invalidSshkey)
{
$qb = $this->createQueryBuilder('d');
$qb->delete()
->where($qb->expr()->in('ssh.id', ':ssh_keys_id'))
->setParameter('ssh_keys_id', $invalidSshkey)
->join('d.sshKeys', 'ssh')
;
return $qb->getQuery()->execute();
}
But this QB return this error
[Doctrine\ORM\Query\QueryException]
[Semantical Error] line 0, col 39 near 'ssh.id IN(:s': Error: 'ssh' is not defined.
[Doctrine\ORM\Query\QueryException]
DELETE AppBundle\Entity\Domain d WHERE ssh.id IN(:ssh_keys_id)
I don't understand why this is returning ssh is not defined because I have made a join with this alias.
This query builder should work ? I really don't know how too fix this.
Thanks for your help.
why do you want to delete Domain when you just need to delete sshKey from Domain (link between them)?
In Domain entity you can define method removeSshKey like this for example
public function removeSshKey(SshKey $key)
{
$this->sshKeys->removeElement($key);
return $this;
}
Then in controller where you want to delete the link between entities you should call it something like this
$domain = $this->getDoctrine()->getRepository('Domain')->find($domainId);
foreach ($domain->getSshKeys() as $sshKey)
{
if ($sshKey->getId() == $invalidSshKeyId)
{
$domain->removeSshKey($sshKey);
}
}
$em = $this->getDoctrine()->getManager();
$em->flush();
this should delete the link
I'm newbie with PHP. I started work with symfony but i have this problem
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param \Doctrine\Common\Collections\Collection $carList
* #ORM\OneToMany(targetEntity="AppBundle\CarBundle\Entity\Car", mappedBy="name", cascade={"persist"})
*/
private $carList;
//getters and setters
}
*
* #ORM\Entity(repositoryClass="AppBundle\CarBundle\Repository\Entity\CarRepository")
* #ORM\Table(name="car")
*/
class Car
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*
*/
protected $id;
/**
* #ORM\Column(type="string", length=100)
* #ORM\ManyToOne(targetEntity="AppBundle\UserBundle\Entity\User" , inversedBy="carList")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $name;
//getters and setters
}
The stacktrace says:
Symfony\Component\Debug\Exception\ContextErrorException: Notice: Undefined index: name
at n/a
and when i run php bin/console doctrine:schema:validate
[Mapping] FAIL - The entity-class 'AppBundle\UserBundle\Entity\User'
mapping is invalid:
* The association AppBundle\UserBundle\Entity\User#carList refers to the owning side field AppBundle\CarBundle\Entity\Car#name which is not
defined as association, but as field.
*The association AppBundle\UserBundle\Entity\User#carList refers to the owning side field Appbundle\CarBundle\Entity\Car#name which does
not exist
I have no idea whats going on, can you help me?
You are mixing up association names with column names. When you create an association you don't need to manually add the columns for that association, doctrine will work that out for you.
This code (in the Car class) says that the $name field is a normal text column in the car table, which of course is wrong
* #ORM\Column(name="name",type="string", length=100)
What you're describing is that one user can own many cars, and many cars can belong to one user. I'd then call the associations owner and cars, but you are of course free to call them whatever you want. Note that you do not need to define the join columns.
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param \Doctrine\Common\Collections\Collection $cars
* #ORM\OneToMany(targetEntity="AppBundle\CarBundle\Entity\Car", mappedBy="owner", cascade={"persist"})
*/
private $cars;
public function __construct()
{
$this->cars = new \Doctrine\Common\Collections\ArrayCollection();
}
//getters and setters
}
/**
*
* #ORM\Entity(repositoryClass="AppBundle\CarBundle\Repository\Entity\CarRepository")
* #ORM\Table(name="car")
*/
class Car
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\UserBundle\Entity\User" , inversedBy="cars")
*/
private $owner;
//getters and setters
}
Read more: Doctrine association mapping
Hope it makes sense :)
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
}