ManytoMany Doctrine - symfony

I have the following field:
/**
* Many Organization have Many PartnerCategory.
*
* #ORM\ManyToMany(targetEntity="PartnerCategory", inversedBy="organizations")
* #ORM\JoinTable(name="partnercategory_organization_map",
* joinColumns={#ORM\JoinColumn(name="organization_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="partnercategory_id", referencedColumnName="id")}
* )
*/
protected $partnerCategories;
how can i make Unique to false!?

You cannot just disable uniqueness since result table of ManyToMany association have both columns as primary key.
Create your own association class PartnerCategoryOrganization which will contain links between categories and organizations with ManyToOne relation to the both entities. Then replace ManyToMany with OneToMany relation on PartnerCategory and Organization entities.

Related

How to limit OneToMany/ManyToOne associations depth/loop in Doctrine2?

I've 3 doctrine entities. One is User, second is Product and third is ProductUsers.
So, User have OneToMany association with ProductUsers and the same Product have OneToMany association with ProductUsers. ProductUsers has ManyToOne association with both User and Product. Like so:
class Product
{
/**
* #var ProductUsers
*
* #ORM\OneToMany(targetEntity="ProductUsers", mappedBy="product")
*/
private $productUsers;
}
class ProductUsers
{
/**
* #var Product
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Product", inversedBy="productUsers")
* #ORM\JoinColumn(name="product_ID", referencedColumnName="ID")
*/
private $product;
/**
* #var User
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="User", inversedBy="productUsers")
* #ORM\JoinColumn(name="user_ID", referencedColumnName="ID")
*/
private $user;
// extra fields ...
}
class User
{
/**
* #var ProductUsers
*
* #ORM\OneToMany(targetEntity="ProductUsers", mappedBy="user")
*/
private $productUsers;
}
A user can use multiple products and a product can have multiple users. ProductUsers has some extra info about the relation other than just the relation.
The problem is when I fetch one User object it comes with associated ProductUsers and it's associated Product. Not only that but the Product also comes with all it's associated ProductUsers and it's respective User objects which is quite an overhead.
This question closely relates to my problem.
I'm looking to limit that at doctrine level just like what JMSSerializerBundle MaxDepth does. Is there a way to limit such overhead in doctrine?
I faced this issue long time back. I tried lazy loading. Which didn't work as expected and that was not a proper solution to my issue. So I did some R&D and came up with a solution that I don't need a bidirectional relationship from Product to ProductUsers.
I can manage same relationship with unidirectional handling only from ProductUsers side. You will need One-To-Many Association when you need a cascade-persist or similar feature. I wrote a small blog regarding this as well.
So, for your solution, just have Many-To-One association from ProductUsers with both Product and User entity. You will not need any change in your database association.
And when you need Products associated for a single user, you can always save a Querybuilder in Repository to use when you need associated data.
It will save a lot of performance. Hope it helps!

Doctrine2 orphanRemoval ManyToMany only if there are no other records connected

My purpose is to remove the record in the entity artist only if there are no other records of the entity connected soundtrack.
I tried with orphanRemoval in this way:
Soundtrack.php
/**
* #Assert\NotBlank(message = "soundtrack.artists.blank")
* #ORM\ManyToMany(targetEntity="Artist", inversedBy="soundtrack", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinTable(name="soundtrack_artist")
* #ORM\OrderBy({"name" = "ASC"})
**/
private $artists;
Artist.php
/**
* #ORM\ManyToMany(targetEntity="Soundtrack", mappedBy="artists")
*/
private $soundtrack;
but when I delete an entity record soundtrack, also clears the record of the entity artist even if it is linked to other records soundtrack (I think this is what you should expect from orphanRemoval).
Is there a way to remove that record an "orphan" only when no other records connected?
I also tried just like this:
**Soundtrack.php**
/**
* #Assert\NotBlank(message = "soundtrack.artists.blank")
* #ORM\ManyToMany(targetEntity="Artist", inversedBy="soundtrack", cascade={"persist"}, orphanRemoval=true)
* #ORM\JoinTable(name="soundtrack_artist")
* #ORM\OrderBy({"name" = "ASC"})
**/
private $artists;
but does not delete the records entity artist ..
orphanRemoval option explicitly thinks, that owning side object is the only instance that references its children. To make it works you should detach child from parent (unset reference) to make child deleted. With Many-2-many associations you should detach entities on both side (owned and inversed)
See Docs
When using the orphanRemoval=true option Doctrine makes the assumption
that the entities are privately owned and will NOT be reused by other
entities. If you neglect this assumption your entities will get
deleted by Doctrine even if you assigned the orphaned entity to
another one.

Foreign key annotation

I have a quite simple 3 table schema, but I couldn't find the solution for annotating the entity in Symfony2.
This are my tables:
user:
id, name, joined
skill:
id, name, created
user_skills:
user, skill
As you understand the last table can contain several rows for each customer and for each skill, but the there can not be duplicate rows with same user and skill.
How do I annotate the vars Entity of: user_skills
because it is not OneToMany, or ManyToMany, its a simple foreign key for other table.
Sorry, my solution is right if you need all the users skills in Skill entity for later's DB queries. I guess this solution will be fine for you:
class UserSkills
{
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity=\"your route"\Entity\User")
* #ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
*/
private $user;
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity=\"your route"\Entity\Skill")
* #ORM\JoinColumn(name="skill_id", referencedColumnName="skill_id")
*/
private $skill;

Symfony2 ORM FK Composite

I'm new with Symfony2 and Doctrine 2 ORM, then i got a problem with composite FK association.
While the association OneToMany-ManyToOne by a single auto-increment ID works good, i got many troubles with the same kind of association but through a composite PK.
What i would like to do is an entity-structure that mirrors the below shema.
http://imageshack.us/photo/my-images/9/z07m.jpg (Sorry but I cannot insert images into the post)
where
prd_product_data.product_id
prd_product_data.language_id
make up together the PK of 'prd_product_data'
and
prd_product_image.pdoduct_id
prd_product_image.language_id
make up the FK linked to the table 'prd_product_data'.
These below
prd_product_image.pdoduct_id
prd_product_image.language_id
prd_product_image.file_image_id
make up, all together, the PK of 'prd_product_image'.
I read that Doctrine 2.1 and up, supports natively the composed PK - FK association but there are very few examples. Moreover, surfing on the web, i found just scattered fragments of similar situations but nothing of useful.
The main issue now, is that i'm unable to create one unique object for the two ids, like such an unique id.
For example...
Snapshot for the Entity ProductData where "product and language should make up the same object:
/**
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
protected $products_Pimgs;
/**
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="language")
*/
protected $products_Limgs;
Snapshot for the Entity ProductImage where *product_id* and *language_id* made up the FK for the entity ProductData:
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="ProductData", inversedBy="products_Pimgs")
* #ORM\JoinColumn(name="product_id", referencedColumnName="product_id")
*/
protected $product;
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="ProductData", inversedBy="products_Limgs")
* #ORM\JoinColumn(name="language_id", referencedColumnName="language_id")
*/
protected $language;
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="FileImage", inversedBy="files_images")
* #ORM\JoinColumn(name="file_image_id", referencedColumnName="id")
*/
protected $file_image;
From these snapshots it's evident that those keys are working separately.
In the end, this is my doctrine version, taken from the composer:
"doctrine/orm": ">=2.2.3,<2.4-dev",
How can i create an unique reference with two objects with ORM?
Read the documentation chapter Composite Primary Keys.
/**
* #ORM\Id
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
protected $products_Pimgs;
/**
* #ORM\Id
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="language")
*/
protected $products_Limgs;

Doctrine2 symfony2 multiple manytomany relations

i have a Gift entity, this entity has a sender, and a receiver...both from the entity User
a user can be a sender of many gifts to other users. but also a receiver of many gifts from many users
the way i see it, the solution inside my Gift entity would be like this:
/**
* #ORM\ManyToMany(targetEntity="Tracker\UserBundle\Entity\User")
* #ORM\JoinTable(name="gift_user",
* joinColumns={#ORM\JoinColumn(name="sender_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="gift_id", referencedColumnName="id")}
* )
*/
protected $senders;
/**
* #ORM\ManyToMany(targetEntity="Tracker\UserBundle\Entity\User")
* #ORM\JoinTable(name="gift_user",
* joinColumns={#ORM\JoinColumn(name="receiver_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="gift_id", referencedColumnName="id")}
* )
*/
protected $receivers;
but when i run php app/console doctrine:schema:update --dump-sql i get:
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'finaldb.gift_user' already exists.
how do i have to change my syntax, configuration, so i end up with a table like this?
gift_id | sender_id | receiver_id
What you are trying to achieve is not possible without two join tables.
Each #ManyToMany association requires a different join table. That because the join table does not know anything else than two linked entities (without knowing the direction of the association). Also, join tables generated by Doctrine ORM don't have any auto-incremental identifier, since the two references already represent the table's primary key.
Here is the stuff :
You can use joinTable to specific the join table name
/**
* #ORM\ManyToMany(targetEntity="Tracker\UserBundle\Entity\User")
* #ORM\JoinTable(name="gift_user",joinTable="myprefix_mytable_senders",
* joinColumns={#ORM\JoinColumn(name="sender_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="gift_id", referencedColumnName="id")}
* )
*/
protected $senders;
/**
* #ORM\ManyToMany(targetEntity="Tracker\UserBundle\Entity\User")
* #ORM\JoinTable(name="gift_user",joinTable="myprefix_mytable_receivers"
* joinColumns={#ORM\JoinColumn(name="receiver_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="gift_id", referencedColumnName="id")}
* )
*/
protected $receivers;

Resources