I have been struggling with this question for the past couple of hours and haven't been able to find anything.
I have configured the FOSUserBundle and have the groups activated correctly and working. However, the user-group relation is defined as follows in the User class :
/**
* #ORM\ManyToMany(targetEntity="Netlabs\UserBundle\Entity\Group")
* #ORM\JoinTable(name="fos_user_user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
and in the Group class, I do not even have a $user list defined. I tried loads of "normal" things like creating a $users variable in my Group class and defining it's relation to the User object, but it is not playing nice with the FOSUserBundle (every time, it creates a NEW table to create the relation, when there is already one in place). For example:
/**
* #ORM\ManyToMany(targetEntity="Netlabs\UserBundle\Entity\Group", inversedBy="groups", cascade={"all"})
*
*/
protected $users;
Any suggestions ?
Again, my main goal is : I want to be able to do Group->getUsers()
In your Group class, your targetEntity must be User and not Group. Furthermore, try to add an inversedBy rule for the $groups attributs and modifie inversedBy in mappedBy for $users.
/**
* #ORM\ManyToMany(targetEntity="Netlabs\UserBundle\Entity\Group", inversedBy="users")
* #ORM\JoinTable(name="fos_user_user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
And
/**
* #ORM\ManyToMany(targetEntity="Netlabs\UserBundle\Entity\User", mappedBy="groups")
*
*/
protected $users;
Related
So I have the next documents:
/*
* #ODM\Document(collection="role", repositoryClass="AppBundle\Document\Repository\RoleRepository")
*/
class Role implements RoleInterface
{
/**
* #var integer $id
*
* #ODM\Id(strategy="INCREMENT")
*/
private $id;
/**
* #var string $name
*
* #ODM\Field(type="string")
*/
private $name;
/**
* #var ArrayCollection $users
*
* #ODM\ReferenceMany(targetDocument="User", mappedBy="roles", cascade={"all"})
*
* #JMS\Accessor(getter="getUsersToJson")
* #JMS\Expose
* #JMS\Type("array<integer>")
*/
private $users;
and
/**
* #ODM\Document(collection="user", repositoryClass="AppBundle\Document\Repository\UserRepository")
*/
class User implements AdvancedUserInterface
{
/**
* #var integer $id
*
* #ODM\Id(strategy="INCREMENT")
* #ODM\Index(unique=true)
*
* #JMS\Expose
* #JMS\Type("integer")
*/
private $id;
/**
* #var ArrayCollection $roles
*
* #ODM\ReferenceMany(targetDocument="Role", inversedBy="users", cascade={"persist", "refresh"})
*
* #JMS\Expose
* #JMS\Type("ArrayCollection<AppBundle\Document\Role>")
*/
private $roles;
So when I do the patch request to update role I want to set update the list of users which role has. I it completely occurs, but when I go to the database I do not see the role in user which was added in role's user list or I do see the role which I removed from role's user list.
So is this a normal behaviour and I have to delete these references by myself OR I do something wrong?
UPDATE:
Always need to write the question to understand what do I really want...
For editing I use symfony forms.
The main question is: can we have reference with something like both inversedBy relation?
I want to have opportunity to edit user and edit role and they remove or add ids from each other, which they (do not) use.
Currently no, you cannot. One model must own the relationship on one side or the other.
If you have the User model own the relationship to the Role you can set a role(s) to the User while editing it. The users property on the Role model can be an inverse reference to display what users have the Role assigned, but you would have to modify the model with the owning reference to add more users to the role.
I would like to create a notification system. There is a Notification class. A notification can be assigned to more than one users, not just one.
There is a joint table user_notifications, with two columns: user_id and notification_id
The definition of the $notifications in the user class is this:
/**
* #ManyToMany(targetEntity="Notification")
* #JoinTable(name="user_notifications",
* joinColumns={#JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="notification_id", referencedColumnName="id", unique=true)}
* )
**/
private $notifications;
Everything works fine. But I would like to add a new column to the user_notifications table, where I would like to store, if the notification is read by the given user, or not. How should I manage it in Doctrine2?
You will have to refactor your entities to introduce a new and transform your user_notifications adjacency table into an entity.
Solution
Transform you table as follows:
Then refactor your associations as follows:
User entity
...
/**
* #OneToMany(targetEntity="UserNotification", mappedBy="notification_id")
**/
private $notifications;
Notification entity
...
/**
* #OneToMany(targetEntity="UserNotification", mappedBy="user_id")
**/
private $users;
UserNotification entity
/** #Entity **/
class UserNotification {
...
/**
* #ManyToOne(targetEntity="User", inversedBy="notifications")
* #JoinColumn(name="user_id", referencedColumnName="id")
**/
private $user_id;
/**
* #ManyToOne(targetEntity="Notification", inversedBy="users")
* #JoinColumn(name="notification_id", referencedColumnName="id")
**/
private $notification_id;
/** #Column(type="boolean") */
private $read;
You'll need to create new entity with this extra column.
You can find details in this answer: https://stackoverflow.com/a/15630665/1348344
I have two tables "RFQ" and "RFQItem".
First ManyToMany relation I need to make a choose which RFQItems add to RFQ in RFQ form.
Second ManyToMany relation I need to make a new RFQItems when creating new RFQ.
I have configured all, but schema update throws me an error:
The table with name 'rfqgroup.rfq_rfqitem' already exists.
Entity:
/**
* #ORM\ManyToMany(targetEntity="RFQItem")
* #ORM\JoinColumn(referencedColumnName="id", nullable=true)
*/
protected $rfqitem;
/**
* #ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
* #ORM\JoinColumn(referencedColumnName="rfq_id", nullable=true)
*/
protected $rfq_item_title;
It is even possible to make these relations?
You must use the #JoinTable attribute to ensure that the Many-to-Many tables have unique names.
/**
* #ORM\ManyToMany(targetEntity="RFQItem")
* #ORM\JoinTable(name="rfq_rfqitem",
* joinColumns={#ORM\JoinColumn(name="rfq_item_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="rfqgroup_id", referencedColumnName="id")}
* )
*/
public $rfqitem;
/**
* #ORM\ManyToMany(targetEntity="RFQItem")
* #ORM\JoinTable(name="rfq_rfqitem_title",
* joinColumns={#ORM\JoinColumn(name="rfq_item_title_id", referencedColumnName="rfq_id")},
* inverseJoinColumns={#ORM\JoinColumn(name="rfqgroup_id", referencedColumnName="id")}
* )
*/
public $rfq_item_title;
You may need to correct the JoinColumn attributes for name and referencedColumnName depending on the variable names you've picked in each entity.
I have the following property in my User entity to track followers and following. Basically a user can follow other user as well. I have a join column called app_user_follow_user, however I also wanted to add a timestamp of whenever someone follows another user, when did it happen. How can I specify a created timestamp via this ORM?
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="following")
*/
protected $followers;
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="followers")
* #ORM\JoinTable(name="app_user_follow_user",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="follow_user_id", referencedColumnName="id")}
* )
*/
protected $following;
Doctrine ManyToMany relationships are used when your join table has two columns. If you need to add another column you have to convert the relationship to OneToMany on both sides and ManyToOne on the joined entity.
This is entirely untested but it will hopefully give you the gist.
User Entity
/**
* #ORM\OneToMany(targetEntity="AppUserFollowUser", mappedBy="appUser")
*/
protected $followers;
/**
* #ORM\OneToMany(targetEntity="AppUserFollowUser", mappedBy="followUser")
*/
protected $following;
AppUserFollowUser Entity
/**
* #ORM\Table(name = "app_user_follow_user")
*/
class AppUserFollowUser
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="User", inversedBy="followers")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $appUser;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="User", inversedBy="following")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="follow_user_id", referencedColumnName="id")
* })
*/
private $followUser;
/**
* #ORM\Column(name="created_date", type="datetime", nullable=false)
*/
private $createdDate;
}
I think that you will have to create a link entity manually (entiy1 onetomany linkEntity manytoone entity2.
Because, the usual link entity are automated and should be as simple and (data less) as possible, so doctrine can take all the controle over it,
imagine you need to get the timestamp, how can you do it on an (none hard coded) entity, you will need a getter, and the annotations are not supposed to contains code.
I have an Author entity, which is a Class Table Inheritance containing an AuthorUser and an AuthorGroup.
/**
* Author
*
* #ORM\Table
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"user" = "AuthorUser", "group" = "AuthorGroup"})
*/
class Author {
// ...
}
AuthorUser relates to my User entity and AuthorGroup to my Group entity.
class AuthorUser extends Author
{
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User", inversedBy="?????")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
}
class AuthorGroup extends Author
{
/**
* #var Group
*
* #ORM\ManyToOne(targetEntity="Group", inversedBy="?????")
* #ORM\JoinColumn(name="group_id", referencedColumnName="id")
*/
protected $user;
}
I have no idea how to inverse this. Anyway, the problem is that i have to add this CTI to my Article entity field. How can i relate using ManyToOne to this Article entity field?
class Article
{
/**
* #var Author
*
* #ORM\ManyToOne(targetEntity="Author", inversedBy="?????????")
* #ORM\JoinColumn(name="author_id", referencedColumnName="id")
*/
protected $author;
}
I'm not sure how to make this as transparent as possible. When i create a new Article, i need to provide either an User or Group object to the author field. I followed this behavior, but it doesn't seem to help. It gets even more complicated.
One solution could be to always have AuthorGroups, even when there's only one Author.
Otherwise, take a look at https://github.com/FabienPennequin/DoctrineExtensions-Rateable
You might be able to use that code to provide a similar Authored interface that can discriminate between the AuthorUser and AuthorGroup.