How to diff and intersect Many-To-Many Self-referencing ArrayCollections - symfony

I have Many-To-Many Self-referencing relation in my user entity.
// Acme\DemoBundle\Resources\config\doctrine\User.orm.yml
Acme\DemoBundle\Entity\User:
type: entity
repositoryClass: Acme\DemoBundle\Entity\Repository\UserRepository
table: users
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
username:
type: string
length: 25
unique: true
manyToMany:
friendsWithMe:
targetEntity: User
mappedBy: myFriends
myFriends:
targetEntity: User
inversedBy: friendsWithMe
joinTable:
name: friends
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
friend_user_id:
referencedColumnName: id
Now i want to get three different user collections:
MyFriends - collection of entities with myFriend == true and friendWithMe == false
FriendWithMe - collection of users with myFriend == false and friendWithMe == true
MutualFriends - collection of users with myFriend == true and friendWithMe == true
Standart getMyFriends an getFriendsWithMe (generated in user entity) returns all MyFriends and FriendWithMe records if friends are mutual =(
I tried to dig into the side of the Criteria but it does not work with many-to-many relations.

I think there is a general problem in your design structure. Self-Referencing relations in Doctrine are equal to Mutual relations. The states, that not both users are friends with each others, sounds more like a FriendsRequest. Maybe you should change this behavior to have on relation for MutualFriends and two different relations for MyFriendRequests and RecievedFriendRequest.
Antother possiblity is to use an Relationship Entity like "Friendship" this could look like
// Acme\DemoBundle\Resources\config\doctrine\Friendship.orm.yml
Acme\DemoBundle\Entity\Friendship:
type: entity
repositoryClass: Acme\DemoBundle\Entity\Repository\FriendshipRepository
table: friendship
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
user_one_accepted:
type: boolean
user_two_accepted:
type: boolean
manyToOne:
user_one:
targetEntity: User
user_two:
targetEntity: User

Related

Doctrine - Unable to persist entity with composite key

I'm using Doctrine with YML mappings. I have two entities. One Group entity and one User entity.
I'm trying to set it up so Users have unique names within a group.
I can create a User, assign it a Group, and save it to the DB. But when I try to create a User with the same name and a different Group, then I get an error saying the unique constraint on name is violated.
Why can't I persist that User?
Their mappings look like this:
Entity\Group:
type: entity
table: groups
id:
id:
type: guid
nullable: false
id: true
generator:
strategy: AUTO
fields:
name:
type: text
nullable: true
Entity\User:
type: entity
table: users
id:
group:
associationKey: true
nullable: false
name:
type: string
manyToOne:
Group:
targetEntity: Entity\Group
joinColumn:
name: group
referencedColumnName: id
I eventually figured this out. I was confusing Doctrine.
The non-standard thing was that I'm using a capitalized parameter name to represent an object and changing that to lowercase for the table column. I did this in the manyToOne: section using name:.
The documentation doesn't really do this, so I didn't know that I still had to reference the capitalized property name in the id: section and separately define the column name there.
So, I changed the User mapping to this:
Entity\User:
type: entity
table: users
id:
Group:
column: group
associationKey: true
nullable: false
name:
type: string
manyToOne:
Group:
targetEntity: Entity\Group
joinColumn:
name: group
referencedColumnName: id

Doctrine2 The association mapping 'ManyToMany' misses the 'targetEntity' attribute. Exception

I want to create three tables use symfony2 and doctrine. Firm , Category and CategoryRelation. This two table have manyToMany relation , i will this relations keep in categoryRelation table. My yml mapping is;
Firm:
// other columns
ManyToMany:
categories:
targetEntity: Category
joinTable:
name: category_relation
joinColumns:
firm_id:
referencedColumnName: id
inverseJoinColumns:
category_id:
referencedColumnName: id
Category:
// other columns
manyToMany:
firms:
targetEntity: Firm
mappedBy: categories
and give me this error
The association mapping 'ManyToMany' misses the 'targetEntity' attribute.
How can I resolve this error? Thanks for answers
I compared your code with the example code of http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html, section 5.14. Many-To-Many, Bidirectional. I paste that code below:
User:
type: entity
manyToMany:
groups:
targetEntity: Group
inversedBy: users
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
Group:
type: entity
manyToMany:
users:
targetEntity: User
mappedBy: groups
I've seen some differences which could produce that Exception. Firstly, you doesn't write the type: entity directive. Your first manyToMany directive has the first M in capital letter. The inversedBy directive doesn't exist. And finally I think this is the main problem, your directives targetEntity and mappedBy are not indented:
firms:
targetEntity: Firm
mappedBy: categories
And YAML is based on the indentation, therefore, probably this is the targetEntity specified in the Exception. You should write it in this way:
firms:
targetEntity: Firm
mappedBy: categories

How to map a table to itself in Doctrine ORM using a self referencing relationship.

There is a User class which has two types of users such as patient and doctor. So, I created another attribute that is used to describe the relation between patient and doctor, a doctor can have many patients. So, If the user is patent, he should have doctorId, if not, the doctorId is NULL.
Here is my User.orm.yml:
Acme\Bundle\DemoBundle\Entity\User:
type: entity
table: User
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 30
lastName:
type: string
length: 30
email:
type: string
length: 60
unique: true
username:
type: string
length: 10
unique: true
password:
type: string
length: 100
unique: false
doctorId:
type: integer
unique: false
nullable: true
dateCreated:
type: datetime
manyToMany:
roles:
targetEntity: Role
mappedBy: users
How can I map the doctorId as a foreign key that refers to the id?
You can find instructions for self-referencing One-To-Many relations in the Doctrine documentation:
User:
type: entity
oneToMany:
patients
targetEntity: User
mappedBy: doctor
manyToOne:
doctor:
targetEntity: User
inversedBy: patients
http://docs.doctrine-project.org/en/latest/reference/association-mapping.html#one-to-many-self-referencing
With doctrine you might want to take a look at association mapping. http://docs.doctrine-project.org/en/latest/reference/association-mapping.html. In your case you are after a one to many self referencing relationship http://docs.doctrine-project.org/en/latest/reference/association-mapping.html#one-to-many-self-referencing.
A doctor can have many patients but can a patient have many doctors? If so you have a many to many relationship which you could map out using a cross Reference table as the joining table. The best way to model this I feel is to have a userTypeId in your users Table where a value of 1 could be doctor, 2 a patient etc. Then a doctor can have many patients but also a patient can see many doctors. This would also be extensible if you added new user types like nurses etc.

Two OnetoMany relationships on an entity causes error?

I have an entity called Reservations that has two relationships with other tables.
reservation.orm.yml
oneToMany:
emails:
targetEntity: Acme\EmailBundle\Entity\Email
mappedBy: reservation
oneToMany:
texts:
targetEntity: Acme\TextBundle\Entity\Text
mappedBy: reservation
email.orm.yml
manyToOne:
reservation:
targetEntity: Acme\ReservationBundle\Entity\Reservation
inversedBy: emails
joinColumn:
name: reservation_id
referencedColumnName: id
text.orm.yml
manyToOne:
reservation:
targetEntity: Acme\ReservationBundle\Entity\Reservation
inversedBy: texts
joinColumn:
name: reservation_id
referencedColumnName: id
Using this code, I have access to the texts by doing
$reservation->getTexts();
However, when I do
$reservation->getEmails();
Symfony returns NULL, even though in my database, the email has a reservation ID of the reservation I'm trying to get the emails of. So, from what it seems like, it creates the email and sets the reservation, but for some reason I'm unable to get the emails for those reservations, in PHP or Twig.
I think this is because I didn't define my relationships correctly, though they are basically cookie-cutter many-to-one. The order that they are placed is screwing it up. In my reserations PHP, I do create an array collection to store emails just like texts. Don't know what's going on....
Try this for the reservations yml file..
oneToMany:
oneToMany:
texts:
targetEntity: Acme\TextBundle\Entity\Text
mappedBy: reservation
emails:
targetEntity: Acme\EmailBundle\Entity\Email
mappedBy: reservation

Doctrine2 gives me only first instance of related objects

I am using QueryBuilder to get 10 biggest cities with states.
$query = $em->createQueryBuilder()
->select('c','s')
->from('CitiesBundle:Cities', 'c')
->innerJoin('c.state', 's','WITH', 'c.state = s')
->orderBy('c.population', 'DESC')
->setMaxResults(10)
->getQuery();
generated SQL:
SELECT c0_.id AS id0, c0_.name AS name1, c0_.landarea AS landarea2,
c0_.density AS density3, c0_.population AS population4, s1_.id AS id5,
s1_.name AS name6, c0_.state_id AS state_id7 FROM cities c0_ INNER
JOIN states s1_ ON c0_.state_id = s1_.id AND (c0_.state_id = s1_.id)
ORDER BY c0_.population DESC LIMIT 10
When I testiing that query in PHPMyAdmin every city has own state, but in app all cities in the array has association with state of first city.
Could somebody explain for me Doctrine2 behaviour in this case?
[EDIT]
Schema:
XYZ\Bundle\CitiesBundle\Entity\Cities:
type: entity
table: cities
fields:
#fields
oneToMany:
state:
targetEntity: States
cascade: { }
mappedBy: null
inversedBy: null
joinColumns:
state_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
XYZ\Bundle\CitiesBundle\Entity\States:
type: entity
table: states
fields:
id:
id: true
type: boolean
nullable: false
generator:
strategy: IDENTITY
name:
type: string
length: 50
fixed: false
nullable: false
lifecycleCallbacks: { }
I try different schema option (ManyToOne etc) but with no luck
Screenshoot from PHPMyAdmin, mazowieckie etc are names of states. In my app all 10 cities has state->name mazowieckie.
Screenshoots from app look:
I outputting state name in loop: {{ city.state.name }}

Resources