Api Platform : order on an entity cascade - symfony

With Api Platform, we can order by association.
Documentation :
use ApiPlatform\Core\Annotation\ApiResource;
/**
* #ApiResource(attributes={"order"={"author.username"}})
*/
class Book
{
...
But I want to order on an entity cascade.
For the example below I tested this with this error :
* #ApiResource(
* attributes={
* "order"={"exercises.repetitions.id":"asc"}
* }
* )
[Semantical Error] line 0, col 422 near 'id ASC, rests_a6.id': Error: Class App\Entity\TrainingSerieExercise has no field or association named repetitions.id
TrainingSerie entity :
* #ApiResource(
...
* attributes={
* "order"={"exercises.repetitions.id":"asc"}
* }
* )
*/
class TrainingSerie
{
...
/**
* #var TrainingSerieExercise[]|ArrayCollection
*
* #ORM\OneToMany(
* targetEntity="App\Entity\TrainingSerieExercise",
* mappedBy="serie",
* cascade={"persist"}
* )
* #Groups({
* "trainings_read",
* "training_series_read",
* "training_series_write",
* })
*/
private $exercises;
...
TrainingSerieExercise entity :
...
class TrainingSerieExercise
{
...
/**
* #var TrainingSerieRepetition[]|ArrayCollection
*
* #ORM\OneToMany(
* targetEntity="App\Entity\TrainingSerieExerciseRepetition",
* mappedBy="exercise",
* cascade={"persist"},
* )
* #Groups({
* "training_series_read",
* "training_series_write",
* "training_serie_exercices_write",
* })
*/
private $repetitions;
...
TrainingSerieExerciseRepetition entity :
class TrainingSerieExerciseRepetition
{
...
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #Groups({
* "training_series_read",
* })
*/
private $id;
...

Following this Doctrine doc this will order TrainingSerieExercise::$repetitions by id:
class TrainingSerieExercise
{
...
/**
* #var TrainingSerieRepetition[]|ArrayCollection
*
* #ORM\OneToMany(
* targetEntity="App\Entity\TrainingSerieExerciseRepetition",
* mappedBy="exercise",
* cascade={"persist"},
* )
* #ORM\OrderBy({"id" = "ASC"})
* #Groups({
* "training_series_read",
* "training_series_write",
* "training_serie_exercices_write",
* })
*/
private $repetitions;
...

Related

api platform ManyToMany persist

I need to persist a ManyToMany relation with api platform, but i get a error, i've tried with cascade={"persist"} and with groups.
When i send the request with the object, i get; Nested documents for attribute "idVehicles" are not allowed. Use IRIs instead.
{
"name": "carl",
"lastName": "abs",
"idVehicles": [
{
"license": "1212121"
}
]
}
here is my users entity:
/**
* Users
*
* #ORM\Table(name="users")
* #ORM\Entity
* #ApiResource(
* attributes={"pagination_enabled"=false},
* normalizationContext={"groups"={"users_read"}},
* denormalizationContext={"groups"={"users_write"}},
* )
*/
class Users
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="users_id_seq", allocationSize=1, initialValue=1)
* #Groups({"users_read", "users_write"})
*/
private $id;
/**
* #var string|null
*
* #ORM\Column(name="name", type="string", length=128, nullable=true)
* #Groups({"users_read", "users_write"})
*/
private $name;
/**
* #var string|null
*
* #ORM\Column(name="last_name", type="string", length=128, nullable=true)
* #Groups({"users_read", "users_write"})
*/
private $lastName;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Vehicles", mappedBy="idUsers", cascade={"persist"})
* #Groups({"users_read", "users_write"})
*/
private $idVehicles;
}
here is my vehicles entity:
/**
* Users
*
* #ORM\Table(name="users")
* #ORM\Entity
* #ApiResource(attributes={"pagination_enabled"=false})
*/
class Users
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="vehicles_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string|null
*
* #ORM\Column(name="license", type="string", length=16, nullable=true, cascade={"persist"})
* #Groups({"users_read", "users_write"})
*/
private $license;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Users", inversedBy="idUsers")
* #ORM\JoinTable(name="users_vehicles",
* joinColumns={
* #ORM\JoinColumn(name="id_vehicles", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_users", referencedColumnName="id")
* }
* )
*/
private $idUsers;
Are you sure you update your schema ? I test your code and it's working

Api Platform 2.5: execute collectionOperations only when the current entity is nested

I started using API Platform after having a good documentation and watching a professionnel tutoriel, and now I encountered a problem.
I have two entities User & Role, the Role is nested in User.
I want to disable direct operations on Role, I want only when I post a User with Role, the post operation works but when I post directly on Role /api/roles, the post operation have to be disabled.
User:
/**
* #ApiResource(
* normalizationContext={
* "groups"={"get"}
* },
* itemOperations={
* "get"={
* "security"="is_granted('IS_AUTHENTICATED_ANONYMOUSLY')",
* "normalization_context"={
* "groups"={"get"}
* }
* },
* "put"= {
* "security"="is_granted('IS_AUTHENTICATED_ANONYMOUSLY') or is_granted('IS_AUTHENTICATED_FULLY') and object.getAuthor() == user",
* "denormalization_context"={
* "groups"={"put"}
* }
* }
* },
* collectionOperations={
* "get"={
* "security"="is_granted('IS_AUTHENTICATED_ANONYMOUSLY')"
* },
* "post"={
* "security"="is_granted('IS_AUTHENTICATED_ANONYMOUSLY')",
* "denormalization_context"={
* "groups"={"user:post"}
* }
* }
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*
* #UniqueEntity(fields={"username","email"})
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*
* #Groups({"get","get_comment_with_author","get_post_with_comments"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*
* #Groups({"get","user:post","get_comment_with_author","get_post_with_comments"})
*/
private $username;
/**
* #ORM\Column(type="string", length=255)
*
* #Groups({"put","user:post","get_comment_with_author","get-to-admin"})
*/
private $email;
/**
* #ORM\ManyToMany(targetEntity="Role", fetch="EAGER")
* #Groups({"put","user:post"})
*/
private $rolesCollection;
Role:
/**
* #ApiResource()
* #ORM\Entity(repositoryClass="App\Repository\RoleRepository")
*/
class Role
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"user:post"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $label;
You can disable operations (but the get operation) like this:
/**
* #ApiResource(
* collectionOperations={"get"},
* itemOperations={"get"}
* )
* #ORM\Entity(repositoryClass="App\Repository\RoleRepository")
*/
class Role
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"user:post"})
*/
private $id;
...
}
Now you can only read the Roles, but not create or edit them.

Upload file for each translation

I have a form with fields that are translated. One of this fields is a file, witch must to be uploaded (each language have different file).
I am using 'stof/doctrine-extensions-bundle' and 'a2lix/translation-form-bundle' and for uploading files 'vich/uploader-bundle' with symfony2.
found this https://github.com/a2lix/TranslationFormBundle/issues/83, but it's not working
Maximum function nesting level of '100' reached, aborting!
My Catalog entity:
/**
* Catalog.
*
* #ORM\Entity()
* #ORM\Table("catalog")
*
* #Vich\Uploadable
*
* #Gedmo\TranslationEntity(class="Entity\Catalog\CatalogTranslation")
*/
class Catalog
{
/**
* #var int
*
* #ORM\Column(type="integer")
* #ORM\Id()
* #ORM\GeneratedValue()
*/
private $id;
/**
* #var string
*
* #ORM\Column()
*
* #Gedmo\Translatable()
*
* #Assert\NotBlank()
*/
private $name;
/**
* #var File
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
*
* #Assert\Image(maxSize = "4M")
*/
protected $imageFile;
/**
* #var string
*
* #ORM\Column(nullable=true)
* #Gedmo\Translatable()
*/
protected $imageName;
/**
* #ORM\OneToMany(
* targetEntity="CatalogTranslation",
* mappedBy="catalog",
* cascade={"persist", "remove"}
* )
*/
private $translations;
}
Also tried this when building form:
->add('imageName', 'a2lix_translationsForms', [
'form_type' => 'vich_file',
'form_options' => array(
'required' => true,
'mapping' => 'product_image',
'allow_delete' => true,
'download_link' => true,
)
])
My guess is that CatalogTranslation should be the class defined as Uploadable as otherwise it will probably confuse VichUploaderBundle.
I'd try something like this:
<?php
/**
* Catalog.
*
* #ORM\Entity()
* #ORM\Table("catalog")
*
* NOT uploadable
*
* #Gedmo\TranslationEntity(class="Entity\Catalog\CatalogTranslation")
*/
class Catalog
{
/**
* #var int
*
* #ORM\Column(type="integer")
* #ORM\Id()
* #ORM\GeneratedValue()
*/
private $id;
/**
* #var string
*
* #ORM\Column()
*
* #Gedmo\Translatable()
*
* #Assert\NotBlank()
*/
private $name;
/**
* #var string
*
* #ORM\Column(nullable=true)
* #Gedmo\Translatable()
*/
protected $imageName;
/**
* #ORM\OneToMany(
* targetEntity="CatalogTranslation",
* mappedBy="catalog",
* cascade={"persist", "remove"}
* )
*/
private $translations;
}
class CatalogTranslation
{
// ... as usual
/**
* #var File
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
*
* #Assert\Image(maxSize = "4M")
*/
protected $imageFile;
protected $imageName;
}

Symfony2 - Count row / Joined Tables

I'm a begginer in Symfony2...
I have a table "TUTORIEL" and an other table 'Groupe_de_categories' linked by 'id_groupe_categorie'
TABLE Tutoriels :
TABLE Groupe_de_categories
I need to count for each "titre_categorie_nv1" (here in my example 'Maison', 'Art&Loisir', 'Enseignement'...) how many "TUTORIEL" I have where "tutoriel_controle" = 'no'
Before to use Synfony2, I hade this code in PHP (works nice):
<?php
$query_nb_cat = "SELECT CATEGORIE, COUNT(*)
FROM Tutoriels
INNER JOIN Groupe_de_categories
ON TUTORIEL.id_groupe_categorie = Groupe_de_categories.id_groupe_categorie
WHERE tutoriel_controle='no'
GROUP BY CATEGORIE_TITLE";
$nb_cat = mysqli_query($BDD_connect, $query_nb_cat)or die(log_mysql($query_nb_cat));
$row_nb_cat = mysqli_fetch_assoc($nb_cat);
do {
$tableau_nb_cat[]=array(
'titre_cat_nv1'=>$row_nb_cat['titre_categorie_nv1'],
'compte_cat_nv1'=>$row_nb_cat['COUNT(*)'],
);
} while ($row_nb_cat = mysqli_fetch_assoc($nb_cat));
$val_cat=array(
'valeur_retour'=>$tableau_nb_cat
);
mysqli_free_result($nb_cat);
mysqli_close($BDD_connect);
?>
The result was something like that :
Maison => 3
Art&Loisir => 9
Enseignement => 14
...
How can I do this with Symfony2 ?
Here is my ORM :
Tutoriel 'Video2LearnBddBundle:Tutoriels':
Tutoriels
{
/**
* #var integer
*
* #ORM\Column(name="id_tutoriel", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idTutoriel;
/**
* #var string
*
* #ORM\Column(name="titre", type="string", length=70, nullable=false)
*/
private $titre;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=false)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="date_creation", type="datetime", nullable=false)
*/
private $dateCreation = 'CURRENT_TIMESTAMP';
/**
* #var string
*
* #ORM\Column(name="nombre_de_vues", type="string", length=45, nullable=true)
*/
private $nombreDeVues;
/**
* #var string
*
* #ORM\Column(name="FAQs", type="string", length=45, nullable=true)
*/
private $faqs;
/**
* #var string
*
* #ORM\Column(name="exclusivite", type="string", nullable=false)
*/
private $exclusivite;
/**
* #var string
*
* #ORM\Column(name="eligible_promotion", type="string", nullable=false)
*/
private $eligiblePromotion;
/**
* #var string
*
* #ORM\Column(name="info_moderateur", type="string", length=300, nullable=true)
*/
private $infoModerateur;
/**
* #var string
*
* #ORM\Column(name="tutoriel_controle", type="string", nullable=false)
*/
private $tutorielControle = 'non';
/**
* #var string
*
* #ORM\Column(name="niveau_choix_categorie_autre", type="string", nullable=true)
*/
private $niveauChoixCategorieAutre;
/**
* #var string
*
* #ORM\Column(name="categorie_autre", type="string", length=45, nullable=true)
*/
private $categorieAutre;
/**
* #var \GroupeDeCategories
*
* #ORM\ManyToOne(targetEntity="GroupeDeCategories")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_groupe_categorie", referencedColumnName="id_groupe_categorie")
* })
*/
private $idGroupeCategorie;
/**
* #var \Membres
*
* #ORM\ManyToOne(targetEntity="Membres")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_membre", referencedColumnName="id_membre")
* })
*/
private $idMembre;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="MotsCles", inversedBy="idTutoriel")
* #ORM\JoinTable(name="mots_cles_et_tutoriels",
* joinColumns={
* #ORM\JoinColumn(name="id_tutoriel", referencedColumnName="id_tutoriel")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="mots_cles", referencedColumnName="mots_cles")
* }
* )
*/
private $motsCles;
Groupe_de_categorie GroupeDeCategories:
<?php
namespace Video2Learn\BddBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* GroupeDeCategories
*
* #ORM\Table(name="Groupe_de_categories", indexes={
* #ORM\Index(name="fk_Groupe_de_categories_Categories_nv11_idx", columns={"titre_categorie_nv1"}),
* #ORM\Index(name="fk_Groupe_de_categories_Categories_nv21_idx", columns={"titre_categorie_nv2"}),
* #ORM\Index(name="fk_Groupe_de_categories_Categories_nv31_idx", columns={"titre_categorie_nv3"}),
* #ORM\Index(name="fk_Groupe_de_categories_Categories_nv41_idx", columns={"titre_categorie_nv4"}),
* #ORM\Index(name="fk_Groupe_de_categories_Categories_nv51_idx", columns={"titre_categorie_nv5"})
* })
* #ORM\Entity
*/
class GroupeDeCategories
{
/**
* #var integer
*
* #ORM\Column(name="id_groupe_categorie", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idGroupeCategorie;
/**
* #var \CategoriesNv1
*
* #ORM\ManyToOne(targetEntity="Video2Learn\BddBundle\Entity\CategoriesNv1", inversedBy="GroupeDeCategories")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="titre_categorie_nv1", referencedColumnName="titre_categorie_nv1")
* })
*/
private $titreCategorieNv1;
/**
* #var \CategoriesNv2
*
* #ORM\ManyToOne(targetEntity="CategoriesNv2")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="titre_categorie_nv2", referencedColumnName="titre_categorie_nv2")
* })
*/
private $titreCategorieNv2;
/**
* #var \CategoriesNv3
*
* #ORM\ManyToOne(targetEntity="CategoriesNv3")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="titre_categorie_nv3", referencedColumnName="titre_categorie_nv3")
* })
*/
private $titreCategorieNv3;
/**
* #var \CategoriesNv4
*
* #ORM\ManyToOne(targetEntity="CategoriesNv4")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="titre_categorie_nv4", referencedColumnName="titre_categorie_nv4")
* })
*/
private $titreCategorieNv4;
/**
* #var \CategoriesNv5
*
* #ORM\ManyToOne(targetEntity="CategoriesNv5")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="titre_categorie_nv5", referencedColumnName="titre_categorie_nv5")
* })
*/
private $titreCategorieNv5;
Thanks !
You can do it by using createQueryBuilder in your repository, or you can use your current query as NativeQuery
Here is a sample (I assume the name of your entities are Tutoriels and GroupeDeCategories)
$em = $this->getDoctrine()->getManager();
$query = $em->getRepository('YourBundle:Tutoriels')
->createQueryBuilder('T')
->join('T.idGroupeCategorie', 'GC')
-->select('COUNT(GC.titreCategorieNv1) AS CT1')
->where("T.tutorielControle = 'no'")
->groupBy('GC.titreCategorieNv1')
->getQuery();
$result = $query->getScalarResult(); //This will return an array of the counts
In your entity I could not find CATEGORIE_TITLE to use in GroupBy and CATEGORIE to add in the selection; so I grouped them by titreCategorieNv1. You can add more fields for your select.
Maybe this link helps you more Symfony CreateQueryBuilder
I did that :
public function updateAction($type_update)
{
$request = Request::createFromGlobals();
$result = $request->isXmlHttpRequest();
if ($result === true) {
switch ($type_update) {
case "compteur_menu":
$em = $this->getDoctrine()->getManager();
$result = $em->createQuery("
SELECT TC.titreCategorieNv1, COUNT(TC.titreCategorieNv1) AS num
FROM Video2LearnBddBundle:Tutoriels T
INNER JOIN T.idGroupeCategorie GC
INNER JOIN GC.titreCategorieNv1 TC
WHERE T.tutorielControle='non'
GROUP BY TC.titreCategorieNv1"
)
->getResult();
$response = new Response();
$response->setStatusCode(Response::HTTP_OK);
$response->setContent(json_encode($result));
$response->headers->set('Content-Type', 'application/json');
return $response;
default:
break;
}
}
}
You can do a repository (more infos here : http://symfony.com/fr/doc/current/book/doctrine.html )
And you could use Doctrine Query Language.
But I think your struture is wrong and it wold be better to have a category, this category has a parent category, ...
So you'll have for example a rootcatégory who has childs named "Bricolage", "Sport", ...
"Bricolage" would have, for exemple a category "Peinture" as child, and so on ;)

Doctrine2 Map entities with composite foreign keys in the composite primary keys

I have a model which has many tables, but in this case we only need three.
The point is that the composite primary key of one is also the foreing key (composite too) and Symfony throws this exception:
MappingException: It is not possible to map entity 'Your\SomethingBundle\Entity\Empleado' with a composite primary key as part of the primary key of another entity 'Your\SomethingBundle\Entity\EmpleadoHorario#empleado'.
Here I explain the relationship:
1º Salon, it has a primary key ID
2º Empleado, it has a composite primary key ID, Salon_id and, also in the primary key, a foreing key referencing Salon: Salon_id
3º EmpleadoHorario: it has a composite primary key Fecha, Empleado_id, Salon_id and, also in the primary key, two a foreing keys referencing Salon: Salon_id, and Empleado: Empleado_id, Salon_id
All the relations has also the inverse union. Here is the code:
The Salon Entity:
/**
* Salon
*
* #ORM\Table(name="salon")
* #ORM\Entity
*/
class Salon
{
/**
* #var string
*
* #ORM\Column(name="id", type="string", length=50, nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
// More fields...
/**
* #var array_collection
*
* #ORM\OneToMany(targetEntity="Empleado", mappedBy="salon")
*/
private $empleados;
/**
* #var array_collection
*
* #ORM\OneToMany(targetEntity="EmpleadoHorario", mappedBy="salon")
*/
private $empleadoHorarios;
// Getters & Setters...
}
The Empleado Entity:
/**
* Empleado
*
* #ORM\Table(name="empleado")
* #ORM\Entity
*/
class Empleado
{
/**
* #var integer
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $id;
/**
* #var string
*
* #ORM\JoinColumn(name="salon_id", referencedColumnName="id", nullable=false)
* #ORM\ManyToOne(targetEntity="Salon", inversedBy="empleados")
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $salon;
// More fields...
/**
* #var array_collection
*
* #ORM\OneToMany(targetEntity="EmpleadoHorario", mappedBy="salon")
*/
private $empleadoHorarios;
// Getters & setters...
}
And finally the EmpleadoHorario Entity:
/**
* EmpleadoHorario
*
* #ORM\Table(name="empleado_horario")
* #ORM\Entity
*/
class EmpleadoHorario
{
/**
* #var \DateTime
*
* #ORM\Column(name="fecha", type="date", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $fecha;
/**
* #var string
*
* #ORM\JoinColumn(name="salon_id", referencedColumnName="id", nullable=false)
* #ORM\ManyToOne(targetEntity="Salon", inversedBy="empleadoHorarios")
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $salon;
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="Empleado", inversedBy="empleadoHorarios")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="salon_id", referencedColumnName="salon_id", nullable=false),
* #ORM\JoinColumn(name="empleado_id", referencedColumnName="id", nullable=false)
* })
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $empleado;
// More fields...
// Getters & Setters...
}
As I said above, the problem seems to be in the EmpleadoHorario.empleado field, which is part of a composite primary key and also composite foreing key.
Other answers across StackOverflow.com suggest the Mapping Inheritance, but I don't even know how it works. I tried twice after reading this but I couldn't solve my problem.
This sample code is illustration of my (temporary) solution :
<?php
namespace X;
use Doctrine\ORM\Mapping as Orm;
/**
* #Orm\Entity
* #Orm\Table(name="A")
*/
class A {
/**
* #Orm\Id
* #Orm\Column(name="id", type="integer")
* #Orm\GeneratedValue(strategy="NONE")
*
* #var integer
*/
private $id;
/**
* #Orm\Id
*
* #var string
*/
private $otherId;
/**
* #Orm\OneToMany(targetEntity="B", fetch="LAZY", mappedBy="a")
*
* #var array
*/
private $collectionOfB;
// getter, setter and other props/methods
}
/**
* #Orm\Entity
* #Orm\Table(name="B")
*/
class B {
/**
* #Orm\Id
* #Orm\Column(name="code")
*
* #var string
*/
private $code;
/**
* #Orm\Id
* #Orm\Column(name="a_id", type="integer")
*
* #var integer
*/
private $a_id;
/**
* #Orm\Id
* #Orm\Column(name="a_other_id")
*
* #var integer
*/
private $a_other_id;
/**
* #Orm\ManyToOne(targetEntity="A", fetch="LAZY", inversedBy="collectionOfB")
* #Orm\JoinColumns({#Orm\JoinColumn(name="a_id", referencedColumnName="id"), #Orm\JoinColumn(name="a_other_id", referencedColumnName="other_id")})
*
* #var A
*/
private $a;
/**
* #Orm\OneToOne(targetEntity="C", fetch="LAZY", mappedBy="b")
*
* #var C
*/
private $c;
// bla bla bla
}
/**
* #Orm\Entity
* #Orm\Table(name="C")
*/
class C {
/**
* #Orm\Id
* #Orm\Column(name="a_id", type="integer")
*
* #var integer
*/
private $a_id;
/**
* #Orm\Id
* #Orm\Column(name="a_other_id")
*
* #var integer
*/
private $a_other_id;
/**
* #Orm\Id
* #Orm\Column(name="b_code")
*
* #var string
*/
private $b_code;
/**
*
* #Orm\OneToOne(targetEntity="B", fetch="LAZY", inversedBy="c")
* #Orm\JoinColumns({#Orm\JoinColumn(name="a_id", referencedColumnName="a_id"), #Orm\JoinColumn(name="a_other_id", referencedColumnName="a_other_id"), #Orm\JoinColumn(name="b_code", referencedColumnName="b_code")})
*
* #var B
*/
private $b;
// bla bla bla
}
Another also ugly solution is just to give AUTOINCREMENT unique PK for EmpleadoHorario like id for instance and remove #ORM\Id and #ORM\GeneratedValue(strategy="NONE") notations from EmpleadoHorario. So finally it will look like:
/**
* EmpleadoHorario
*
* #ORM\Table(name="empleado_horario")
* #ORM\Entity
*/
class EmpleadoHorario
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="fecha", type="date", nullable=false)
*/
private $fecha;
/**
* #var string
*
* #ORM\JoinColumn(name="salon_id", referencedColumnName="id", nullable=false)
* #ORM\ManyToOne(targetEntity="Salon", inversedBy="empleadoHorarios")
*/
private $salon;
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="Empleado", inversedBy="empleadoHorarios")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="salon_id", referencedColumnName="salon_id", nullable=false),
* #ORM\JoinColumn(name="empleado_id", referencedColumnName="id", nullable=false)
* })
*/
private $empleado;
// More fields...
// Getters & Setters...
}

Resources