I have a Symfony controller action which adds a specified user to the list of followed users (the list is a ManyToMany
). The code is quite simple:
public function followUserAction(Request $request, User $followee, $follow)
{
/** @var User */
$user = $this->getUser();
// same user
if ($user === $followee) {
return;
}
$em = $this->getDoctrine()->getManager();
$follow = boolval($follow);
if ($follow && !$user->getFollowedUsers()->contains($followee)) {
$user->addFollowedUser($followee);
} elseif (!$follow && $user->getFollowedUsers()->contains($followee)) {
$user->removeFollowedUser($followee);
}
$em->flush();
}
This is the mapping:
/**
* @var ArrayCollection<int|string, User>
*
* @ORM\ManyToMany(targetEntity="User", fetch="EXTRA_LAZY", inversedBy="followingUsers")
* @ORM\JoinTable(
* joinColumns={@ORM\JoinColumn(name="following_user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="followed_user_id", referencedColumnName="id")}
* )
*/
private $followedUsers;
/**
* @var ArrayCollection<int|string, User>
*
* @ORM\ManyToMany(targetEntity="User", fetch="EXTRA_LAZY", mappedBy="followedUsers")
*/
private $followingUsers;
The problem is that when a user clicks many times I am receiving a Duplicate entry
. I followed the Doctrine's article about concurrency:
But unfortunately it doesn't cover the following case:
- Check if record exists (
SELECT
) - If it doesn't exist => insert it
- If it already exists => do nothing
If two users make the first SELECT
at the same, they will both try to insert the new record.
Any way to solve it?