Symfony doctrine many to many unique - php

I have to entity with manyToMany relation, that i have transform in two OneToMany. So I have create an other Entity called CollanaCollezionista into that i have some attribute.
I want that the couple collana/collezionista is unique, how can i do this on doctrine and symfony?
/**
* Collana
*/
class Collana
{
private $id;
private $titolo;
/**
* #MaxDepth(1)
* #ORM\OneToMany(targetEntity="CollezionistaCollana", mappedBy="collana")
*/
private $collezionisti;
}
/**
* Collezionista
*/
class Collezionista
{
private $id;
private $user;
/**
* #ORM\OneToMany(targetEntity="CollezionistaCollana", mappedBy="collezionista")
*/
private $collane;
}
So I have an other entity, called CollezionistaCollana. How can i set that the couple collezionista-collana is unique?

Answer:
#UniqueConstraint do the stuff.
use Doctrine\ORM\Mapping\UniqueConstraint as UniqueConstraint;
/**
* CollezionistaCollana
*
* #ORM\Table(name="collezionista_collana",uniqueConstraints={#‌UniqueConstraint(nam‌​e="unique_hold", columns={"idCollezionista", "idCollana"})})
* #ORM\Entity
*/
class CollezionistaCollana
{
// Class details
}

Related

Doctrine criteria on subclasses of abstract entity

I have an abstract entity which is inherited by two subclasses. I'm using it in association with other entity and now I want to create criteria to filter out objects with the property set to some value.
My superclass:
/**
* #ORM\MappedSuperclass
* #ORM\Entity(repositoryClass="Foo\Bar\AddressRepository")
* #ORM\InheritanceType(value="SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="discriminator_type", type="string")
* #ORM\DiscriminatorMap({"homeaddress" = "HomeAddress", "companyaddress" = "CompanyAddress"})
*/
abstract class AbstractAddress
{
/**
* #var bool
* #ORM\Column(type="boolean", options={"default": 0})
*/
protected $active;
}
Subclasses:
/**
* #ORM\Entity(repositoryClass="Foo\Bar\AddressRepository")
*/
class HomeAddress extends AbstractAddress
{
}
/**
* #ORM\Entity(repositoryClass="Foo\Bar\AddressRepository")
*/
class CompanyAddress extends AbstractAddress
{
}
Entity with association:
/**
* #ORM\Entity(repositoryClass="Foo\Bar\CustomerRepository")
*/
class Customer
{
/**
* #var ArrayCollection
* #ORM\ManyToMany(targetEntity="Foo\Bar\AbstractAddress", cascade={"all"}, orphanRemoval=true)
*/
private $addresses;
/**
* #return Collection|null
*/
public function getAddresses(): ?Collection
{
return $this->addresses->matching(
Criteria::create()->where(Criteria::expr()->eq('active', true))
);
}
}
This setup produces exception:
ResultSetMapping builder does not currently support your inheritance scheme.
The problem is that it tries to instantiate AbstractAddress instead of one of the subclasses respectively.
Is there any way to achieve this filtering using Criteria API?
I know that I can use filter() instead, but this function doesn't impact SQL query, so I would rather have this solved used criteria.

Doctrine 2 many-to-many with MappedSuperclass in Zend framework 2

I am new to Doctrine2 and trying to create entities for the following DB structure:
I want to have all machine parts as an array in one attribute of the machine class. I tried this:
class Machine {
....
/**
* #var array
* #ORM\OneToMany(targetEntity="MachineHasPart", mappedBy="machine", cascade={"persist", "remove"}, orphanRemoval=TRUE)
*/
private $parts;
....
public function getParts () {
return array_map(
function ($machineHasPart) {
return $machineHasPart->getPart();
},
$this->parts->toArray()
);
}
}
Where MachineHasPart is a #MappedSuperclass for the intermediate entities/tables (like machineHasCylinder etc), but it failed with:
An exception occurred while executing 'SELECT FROM machineHasPart t0'.
Should I restructure my database to use ORM here? Or there is a solution for my case?
You cannot query a #MappedSuperClass. This is also mentioned in the Doctrine2 documentation in chapter 6.1. Mapped Superclasses:
A mapped superclass cannot be an entity, it is not query-able and persistent
This means you have to either change the target entity to something queryable or you have to make MachineHasPart to a entity and change to single table inheritance.
When I look at your database structure I would suggest changing your Machine entity to have three independent relationships for the parts. One for Belt, one for Cylinder and one for Gear.
Then instead of a generic getParts you will have three methods getBelts, getCylinders and getGears.
If that is really not what you want then you can leave a comment.
UPDATE
You can solve it also with class inheritance. First make a base class Part that is also an entity and use it in the other classes Belt, Cylinder and Gear:
Part:
<?php
namespace Machine\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Part
*
* #ORM\Entity
* #ORM\Table("part")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="discriminator", type="string")
* #ORM\DiscriminatorMap({
* "part" = "Part",
* "gear" = "Gear",
* "cylinder" = "Cylinder",
* "belt" = "Belt",
* })
* #property int $id
*/
class Part
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var Machine
* #ORM\ManyToOne(targetEntity="Machine\Entity\Machine", inversedBy="parts")
* #ORM\JoinColumn(name="machine_id", referencedColumnName="id", nullable=true)
*/
protected $machine;
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
*
* #param int $id
* #return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
//... add setters and getters for machine as normal ...
}
Extend this class in your other parts:
Belt:
<?php
namespace Machine\Entity;
/**
* Belt
*
* #ORM\Entity
*/
class Belt extends Part
{
}
Cylinder:
<?php
namespace Machine\Entity;
/**
* Cylinder
*
* #ORM\Entity
*/
class Cylinder extends Part
{
}
Gear:
<?php
namespace Machine\Entity;
/**
* Gear
*
* #ORM\Entity
*/
class Gear extends Part
{
}
Now in your machine relate to the parts like as follows.
Machine:
<?php
namespace Machine\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Machine
*
* #ORM\Entity
* #ORM\Table("machine")
* #property int $id
*/
class Machine
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
*
* #param int $id
* #return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* #var Collection
* #ORM\OneToMany(targetEntity="Machine\Entity\Part", mappedBy="machine")
*/
protected $parts;
public function __constuct()
{
$parts = new ArrayCollection();
}
/**
*
* #return Collection
*/
public function getParts()
{
return $this->parts;
}
//... add setters and getters for parts as normal ...
}
Extend this class in your other parts:
Reading further in the Doctrine2 documentation in chapter 6.1. Mapped Superclasses (referred to by #Wilt):
... Furthermore Many-To-Many associations are only possible if the mapped superclass is only used in exactly one entity at the moment...
This means in this case the ORM mapping doesn't help. I cannot gather the data of all three entities MachineHasCylinder, MachineHasBelt and MachineHasGear through a MappedSupperclass at the same time.
I think using DQL or Native SQL is the only solution for this problem.

Bidirectional association with one column on the inversed side and multiple on the owning side

I am using Doctrine 2. Let's say we have two entities: User and Bug. Is it possible to have a bidirectional association with one column on the inversed side (User) and multiple columns on the owning side (Bug)?
If I define columns in the Bug entity like this:
/** #Entity */
class Bug {
/** #ManyToOne(targetEntity="User", inversedBy="associated_bugs") */
protected $reported_by;
/** #ManyToOne(targetEntity="User", inversedBy="associated_bugs) */
protected $assigned_to;
}
then I don't know what to write in the User entity...
/** #Entity */
class User {
/**
* #OneToMany(targetEntity="Bug", mappedBy="???")
* #var Bug[]
**/
protected $associated_bugs;
}
No this is something you can not do with mapping. Lets say you would set a list of bugs to User::associated_bugs. How would you expect it to store that when calling persist?
You should map the 2 types of bugs separately and next combine them in a method.
/** #Entity */
class User {
/**
* #OneToMany(targetEntity="Bug", mappedBy="reported_by")
* #var Bug[]
**/
protected $reported_bugs;
/**
* #OneToMany(targetEntity="Bug", mappedBy="assigned_to")
* #var Bug[]
**/
protected $assigned_bugs;
protected function getAssociatedBugs()
{
return array_merge($this->reported_bugs, $this->assigned_bugs);
}
}
Something like this:
/** #Entity */
class User {
/**
* #OneToMany(targetEntity="Bug", mappedBy="assigned_to")
**/
protected $associated_bugs;
/**
* #OneToMany(targetEntity="Bug", mappedBy="reported_by")
**/
protected $reported_bugs;
}
In Bug entity, you have to add these annotations:
For assigned bugs:
#JoinColumn(name="assignee_id", referencedColumnName="id", onDelete="cascade")
and
#JoinColumn(name="reporter_id", referencedColumnName="id", onDelete="cascade")
for reported bugs
This should do the job

Symfony2 : Entities not created in database

I'm making entities with Symfony2 and Doctrine2. I made some entities that represent a many-to-many relation between two of my entities.
An example of one of these entities :
/**
* #ORM\Entity
*/
class Contact_Conference_Invitation
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Contact")
*/
private $contact;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\ConferenceBundle\Entity\Conference")
*/
private $conference;
/**
* #var datetime dateInvitation
*
* #ORM\Column(name="dateInvitation", type="datetime")
*/
private $dateInvitation;
//Getters and setters
}
I have tried updating my sql schema, but the tables corresponding to these entities do not appear. Is there somewhere I have to declare them (config or such)? If not, what's wrong?
Thanks a lot
Edit : I had forgotten the namespace for these class, and that's why they were omitted by Doctrine. Another case closed :) thanks for the answers!
Assumptions ...
No, you don't need to declare them anywhere else than in your Entity directory.
What's the error message you got?
I guess you added
use Doctrine\ORM\Mapping as ORM;
on the top of your classes to let them be mapped.
I tried ...
I tried to generate your entities by adding a simple Contact & Conference entities and it's working fine.
Here are the code snippets:
Contact_Conference_Invitation.php
namespace Ahsio\StackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Contact_Conference_Invitation
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Ahsio\StackBundle\Entity\Contact")
*/
private $contact;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Ahsio\StackBundle\Entity\Conference")
*/
private $conference;
/**
* #var datetime dateInvitation
*
* #ORM\Column(name="dateInvitation", type="datetime")
*/
private $dateInvitation;
//Getters and setters
}
Contact.php
namespace Ahsio\StackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Contact
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
Conference.php
namespace Ahsio\StackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Conference
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
Here are the generated tables:
NB: I used a specific namespace for the entities generation to work fine, you need to change them.
Also don't forget to check that you have automapping enabled.
In your config.yml you should have
doctrine:
orm:
auto_mapping: true
Came across this question because my entities weren't generated as well, this was my issue, it could save some time to people struggling with the same issue.
I don't see the definition of your ManyToMany relation in the sample of code you provided.
As an example, here's a ManyToMany relationship I implemented for a project
Entity Project.php
/**
* #var Provider[]
*
* #ORM\ManyToMany(targetEntity="Provider", mappedBy="projects")
*/
protected $providers = null;
Entity Provider.php
/**
* #var Project[]
*
* #ORM\ManyToMany(targetEntity="Project", inversedBy="providers")
* #ORM\JoinTable(name="PROVIDER_PROJECT")
*/
protected $projects = null;
As you can see, here you define the join table for your ManyToMany relationship.
Of course those entities are specific for my particular project but you get the idea and you can adapt it easily for your needs.

one to many relationship problem in doctrine 2.0

I have an events table and events images table. I am having a form to add new event so i am also adding multiple images for that event. So that i am storing in event images table.
so how do i insert the data in both the tables..
<?php
/**
* #Entity
* #Table(name="events")
*/
class Default_Model_Event
{
/**
* #Id #Column(name="id", type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #Column(name="title", type="string")
*/
private $title;
/**
* #OneToMany(targetEntity="Default_Model_EventImages" mappedBy="eventimage_mapper")
*/
private $images_mapper;
}//end class
Event images model
<?php
/**
* #Entity
* #Table(name="event_images")
*/
class Default_Model_EventImages
{
/**
* #Id #Column(name="id", type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #Column(name="name", type="string")
*/
private $name;
/**
* #ManyToOne(targetEntity="Default_Model_Event", inversedBy="images_mapper")
* #JoinColumn(name="event_id", referencedColumnName="id")
*/
private $eventimage_mapper;
}//end class
From my controller how do i save the data now.. I am thinking of first saving the event data and than will get that id and than will save the events images by loop.. than i am not getting what will be the use of the one to many mapper i have created..
I am using zend framework 1.11 and Doctrine 2.0
At first you need to create getters, setters to your objects. Then you just create
$event = new Default_Model_Event();
$em->persist($event);
while (something) {
$image = new Default_Model_EventImages();
$image->setEventimage_mapper($event);
$em->persist($image);
}
$em->flush();
Just read the Doctrine documentation on associations. It will help for sure.

Categories