Doctrine 2 one-to-one via composite key - doctrine-orm

I am trying to set up a relationship as shown below.
Each car can have one review.
A car has a primary key on 2 columns.
Review is referenced back to the car via the composite primary key.
Simple, in theory.
class Car {
/**
* #ORM\Id
* #ORM\Column(type="string")
*/
private $make;
/**
* #ORM\Id
* #ORM\Column(type="string")
*/
private $model;
/**
*
* #ORM\OneToOne(targetEntity="Review", mappedBy="car", cascade={"persist"})
*/
private $review;
}
class Review {
/**
* #ORM\Id
* #ORM\OneToOne(targetEntity="Car", inversedBy="review")
*/
private $car;
/**
* #var #ORM\Column(type="text")
*/
private $text;
}
When I try to generate the schema, the following error pops up.
Column name id referenced for relation from \Entity\Review towards
\Entity\Car does not exist.
What am I doing wrong?

After extensive research, I can say that the above structure is not supported by Doctrine, unfortunately.

Related

Doctrine Single Table Inheritance and bidirectional OneToMany: columns not being generated

The data model:
The entities:
Pet:
/**
* #ORM\Entity
* #ORM\Table(name="pet")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="pet_type", type="string")
*/
abstract class Pet
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToMany(
* targetEntity="Collar",
* mappedBy="pet",
* cascade={"persist", "remove"},
* orphanRemoval=TRUE
* )
* #ORM\JoinColumn(name="collars", referencedColumnName="id")
*/
protected $collars;
/**
* #ORM\Column(type="integer")
*/
protected $age;
}
Cat:
/**
* #ORM\Entity
* #ORM\Table(name="cat")
*/
class Cat extends Pet
{
/**
* #ORM\Column(type="decimal")
*/
private $purringDecibels;
}
Collar:
/**
* #ORM\Entity
* #ORM\Table(name="collar")
*/
class Collar
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Pet", inversedBy="collars")
* #ORM\JoinColumn(name="pet", referencedColumnName="id", nullable=false)
*/
private $pet;
/**
* #ORM\Column(type="string", length="255")
*/
private $color;
}
The problem:
The generated tables are fine except pet: It lacks the collars column, therefore the bidirectionality is broken. While the pet ids do get stored on the collar table, I cannot fetch collars from a pet (i.e. $pet->getCollars()) as it always returns an empty collection.
What am I missing out here?
PS:
The validate console helper says all (mapping & db) is OK.
Yes, I have my getters and setters (i.e. adders and removers)
I know about the infamous performance impact of the combination between a CTI and this kind of relationship.
You do not need to have a "collars" column on the pet table. It is a one-to-many relationship, so the only table that need to "know" about pets are the collar table.
A bidirectional relationship does not mean you need two columns on two tables.
Your map seems correct.

Symfony2 Form with Doctrine Relationship Persistence Issue

So I have 3 entities with their properties.
A USER which has MANY USERSKILLS with each ONE having a single corresponding SKILL
Here are the entities:
/**
* #ORM\Table(name="skills")
* #ORM\Entity()
*/
class Skill
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=30, unique=true)
*/
private $name;
/**
* #ORM\Column(name="active", type="boolean")
* #var bool
*/
private $active = false;
/**
* #ORM\OneToMany(targetEntity="UserSkill", mappedBy="skill")
*/
private $userSkills;
}
/**
* #ORM\Table(name="user_skill")
* #ORM\Entity()
*/
class UserSkill
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="User", inversedBy="skills")
* #var User
*/
private $user;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Skill", inversedBy="userSkills")
* #var Skill
*/
private $skill;
/**
* #ORM\Column(type="integer")
* #var int
*/
private $level = 0;
}
/**
* StartupDriven\UserBundle\Entity\User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="StartupDriven\UserBundle\Entity\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\OneToMany(targetEntity="UserSkill", mappedBy="user")
* #var ArrayCollection
*/
private $skills;
}
They are created using 2 symfony form objects which works fantastically.
The problem is when I go to persist these objects in the controller.... I get an error
$form->handleRequest($request);
if ($form->isValid()) {
/**
* #var User $user
*/
$user = $form->getData();
/**
* #var UserSkill $userSkill
*/
foreach ($user->getSkills() as $userSkill) {
// No updating skills... Only new ones.
if (!$userSkill->getId()) {
// Check skill name match.
if ($matched_skill = $em->getRepository('StartupDrivenUserBundle:Skill')->findOneBy(array('name' => $userSkill->getName()))) {
$userSkill->setSkill($matched_skill);
}
else {
// No match. Create new generic skill.
$em->persist($userSkill->getSkill());
// THE ERROR HAPPENS ON THE FOLLOWING LINE!
$em->flush();
}
// Set the User
$userSkill->setUser($user);
// Persist the user skill.
$em->persist($userSkill);
$em->flush();
}
}
$em->persist($user);
$em->flush();
Error Message:
A new entity was found through the relationship 'StartupDriven\UserBundle\Entity\User#skills' that was not configured to cascade persist operations for entity: StartupDriven\UserBundle\Entity\UserSkill#0000000053e8628e00007f7f2fd56e1f. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'StartupDriven\UserBundle\Entity\UserSkill#__toString()' to get a clue.
I have tried every combination of persist & flush that I can think of. I have tried the cascade option above (which gives a different error that the "user id which is required by the primary key rules is not set")... I am completely lost. It seems like such a simple relationship... Where am I going wrong?

Doctrine composite primary key as well as foregin keys

i have a table which has two columns that are foreign keys from another two tables. I would like to make them composite primary key together as well as foreign key each one.
Here is my Entity from symfony;
/**
* ilan_emlakOzellik
*
* #ORM\Table()
* #ORM\Entity
*/
class ilan_emlakOzellik
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\ManyToOne(targetEntity="ilan")
* #ORM\JoinColumn(name="ilanId")
*/
private $ilanId;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="emlakOzellik")
* #ORM\JoinColumn(name="ozellikId")
* #ORM\Column(type="integer")
*/
private $ozellikId;
After the write this schema to db, i see primary keys but foreign keys are missing. How can i make them foreign key too? Thanks for helping.
Validate your schema - these mappings are incorrect. Either a field is a column, or it is an association. Having both mappings on the same field is not allowed:
/**
* ilan_emlakOzellik
*
* #ORM\Table()
* #ORM\Entity
*/
class ilan_emlakOzellik
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="ilan")
* #ORM\JoinColumn(name="ilanId")
*/
private $ilanId;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="emlakOzellik")
* #ORM\JoinColumn(name="ozellikId")
*/
private $ozellikId;

No identifier/primary key specified for Entity in doctrine 2

I am using Zend 2 Framework and I am trying to get data using Doctrine 2.
However the following error is coming in the Entity file.
Doctrine\ORM\Mapping\MappingException
No identifier/primary key specified for Entity "Acl\Entity\Permission". Every Entity must have an identifier/primary key.
How can I specify the primary key?
I am using the following code.
/**
* User Permissions
*
* #ORM\Entity
* #ORM\Table(name="acl_permissions")
* #property int $id
* #property int $role_id
* #property int $resource_id
* #property string $action
*/
class Permission
{
/**
* #ORM\Column(type="integer")
*/
public $id;
/**
* #ORM\Column(type="integer")
* #ORM\OneToOne(targetEntity="Role")
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
*/
public $role;
/**
* #ORM\Column(type="integer")
* #ORM\OneToOne(targetEntity="Resource")
* #ORM\JoinColumn(name="resource_id", referencedColumnName="id")
*/
public $resource;
/**
* #ORM\Column(type="string")
*/
public $action;
public function getRole()
{
return $this->role;
}
public function getResource()
{
return $this->resource;
}
}
Have you checked the docs?
You can define a primary key by using the #ORM\Id annotation. In case the value is generated automatically (e.g. if using auto_increment), you also need to set the #ORM\GeneratedValue(strategy="IDENTITY") annotation.

Doctrine2: Why is Mapping not detecting my composite keys

I have two tables/entities client and site that have a many to many relationship combined by a join table client_site. Here are how my entities are setup.
Here is the client table entity
/**
* #Entity
* #Table(name="client")
*/
class Client
{
/**
* #Id #Column(type="bigint")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ManyToMany(targetEntity="Site", inversedBy="clients")
* #JoinTable(name="client_site",
* joinColumns={#JoinColumn(name="c_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="s_id", referencedColumnName="id")}
* )
*/
private $sites;
And the site table entity
/**
* #Entity
* #Table(name="site")
*/
class Site
{
/**
* #Id #Column(type="bigint")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ManyToMany(targetEntity="Client", mappedBy="sites")
*/
private $clients;
This is the client_site table entity
/**
* #Entity
* #Table(name="client_site",indexes={#index(name="FK_client_site",columns={"c_id"}),#index(name="FK_client_site_2",columns={"s_id"})})
*/
class ClientSite
{
/**
* #Id
* #ManyToOne(targetEntity="Client", inversedBy="ClientSite")
*/
private $client;
/**
* #Id
* #ManyToOne(targetEntity="Site", inversedBy="ClientSite")
*/
private $site;
This is the query I am trying to run
$query = Zend_Registry::get('em')
->createQuery('SELECT c, s
FROM Application\Models\Client c
JOIN c.sites s
WHERE c.is_active = 1');
$clients = $query->getResult();
And this is my error
No identifier/primary key specified for Entity 'Application\Models\ClientSite'. Every Entity must have an identifier/primary key.
I put the #Id on both fields in the ClientSite entity, as they are the composite primary keys for my joiner table. Can this not be done in Doctrine2? If it can't, what are my alternative options.
If you CAN do this, what have I done incorrectly?
This isn't currently supported by Doctrine 2.
However, they are working on adding support for this in an experimental branch. Apparently this might be included in the 2.1 release if it works without issues.