Doctrine2: Why is Mapping not detecting my composite keys - doctrine-orm

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.

Related

KnpLabs DoctrineBehaviors translatable query count

I am using KnpLabs/DoctrineBehaviors translatable.
I have a Post entity and a BlogCategory entity.
Post.php
class Post
{
use Timestampable;
/**
* #ManyToMany(targetEntity="BlogCategory")
* #JoinTable(name="post_categories")
* #var ArrayCollection
*/
protected $categories;
...
}
class BlogCategory
{
use Translatable;
/**
* #Id()
* #GeneratedValue(strategy="AUTO")
* #Column(type="integer")
* #var int
*/
private $id;
...
}
class BlogCategoryTranslation
{
use Translation;
/**
* #Column()
* #NotBlank()
* #var string
*/
protected $name;
...
}
I want to show posts with related categories. But now I have a lot of queries.
How can I join translation in many-to-many association to optimize query count?
What you're looking for is a LEFT JOIN on the translations:
SELECT post, category, category_trans
FROM Post post
LEFT JOIN post.categories category
LEFT JOIN category.translations category_trans
If you want to only select the translation for the current language:
LEFT JOIN category.translations category_trans WITH category_trans.locale = :locale
(bind a locale parameter to the query).
If you're using query builder:
->leftJoin('category.translations', 'category_trans', 'WITH', category_trans.locale = :locale)

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.

Doctrine multi level inheritance order pblm

When using class table inheritance with multiple levels in doctrine :
Account->User->Dealer
(Dealer inherits from User, User from Account)
Account has the discriminator column and mapping. When persisting a new Dealer entity I get a foreign key error because there is no row in the User table.
So the order in which the insert statements are executed is:
1) Insert into Account
2) Insert into Dealer (which causes the error)
3) insert into User
Can someone help me thanks in advance
this is my configuration :
/**
* #Table(name="Account")
* #Entity
* #InheritanceType("JOINED")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"Account" = "Default_Model_Account","User" = "Default_Model_User","Dealer" = "Default_Model_Dealer"})
*/
class Default_Model_Account {
/**
* #id #column(name="accountID",type="integer")
* #GeneratedValue(strategy="AUTO")
*/
protected $accountID;
/**
* #column(name="email",type="string")
*
*/
protected $email;
}
/**
* #Table(name="User")
* #Entity
*/
class Default_Model_User extends Default_Model_Account{
/**
* #column(name="firstName",type="string")
*/
protected $firstName;
}
/**
* #Entity
* #Table(name="Dealer")
*
*/
class Default_Model_Dealer extends Default_Model_User{
/**
* #column(name="type",type="string")
*/
protected $type;
}

Doctrine 2 ManyToOne with Join Table

I'm looking for a suggestion on how to map a OneToMany/ManyToOne relationship that uses a join table. The mapping I have is not taking, and I get an error that article_id is not set in the media table. 
class Media
{
// ...
/**
* #ManyToOne(targetEntity="Document", inversedBy="media")
* #JoinTable(name="articles_x_media", referencedColumnName="id")
* joinColumns={#JoinColumn(name="media_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="bid_id", referencedColumnName="id")})
* )
*/
protected $document;
}
class Document
{
// ...
/**
* #OneToMany(targetEntity="Media", mappedBy="document"))
* #JoinTable(name="articles_x_media", referencedColumnName="id")
* joinColumns={#JoinColumn(name="article_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="media_id", referencedColumnName="id")}
* )
*/
protected $media;
}
There's a specific paragraph in the documentation about OneToMany mapping with join table.
Anyway, what you probably want is an uni-directional ManyToMany association.
Also, #OneToMany does not come with a #JoinTable, and the same for #ManyToOne either.

Doctrine 2 one-to-one via composite key

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.