I have 2 entities : User And Love. This is a "One-To-Many, Bidirectional".
Here are my entities:
User:
namespace SE\UserBundle\Entity;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="SE\UserBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
//...
/**
* One User has Many Loves.
* #ORM\OneToMany(targetEntity="SE\CoreBundle\Entity\Love", mappedBy="user", cascade={"persist"})
*/
private $loves;
//...
public function __construct()
{
//...
$this->loves = new ArrayCollection();
//...
}
//...
/**
* Remove love
*
* #param \SE\CoreBundle\Entity\Love $love
*/
public function removeLove(\SE\CoreBundle\Entity\Love $love)
{
$this->loves->removeElement($love);
//delete love
}
//...
}
Love :
namespace SE\CoreBundle\Entity;
/**
* Love
*
* #ORM\Table(name="love")
* #ORM\Entity(repositoryClass="SE\CoreBundle\Repository\LoveRepository")
*/
class Love
{
//...
/**
* Many Loves have One User.
* #ORM\ManyToOne(targetEntity="SE\UserBundle\Entity\User", inversedBy="loves", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
//...
/**
* Set user
*
* #param \SE\UserBundle\Entity\User $user
*
* #return Love
*/
public function setUser(\SE\UserBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
//...
}
My question is:
Is there a way, when i execute removeLove() on my User, the corresponding Love entity autodelete in my database without using an entity manager in my controller. I would like my controller to look like that:
class DefaultController extends Controller
{
public function indexAction()
{
//...
$em = $this->getDoctrine()->getManager();
$user->removeLove($love);
$em->persist($user);
$em->flush();
//...
}
}
And the result would be that, $love would not be in getLoves() of the $user and $love would be delete of the database.
You could try: Orphan Removal option
Make sure Entity Love is not associated with another User. So one Entity Love is always associated with only one User
Related
I have a Symfony app whereby a user can send a friend request, which will be received by the other user who can then accept or decline the request thereby creating the relationship. I have an idea of how to implement this, however, my inexperience has to lead me to a wall.
Friends Entity
/**
* #ORM\Entity()
*/
class Friends
{
const STATUS_PENDING = 'STATUS_PENDING';
const STATUS_FRIEND = 'STATUS_FRIEND';
const STATUS_BLOCKED = 'STATUS_BLOCKED';
const DEFAULT_STATUS = [self::STATUS_PENDING];
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="myFriends")
* #ORM\Id
*/
private $user;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="friendsWithMe")
* #ORM\Id
*/
private $friend;
/**
* #ORM\Column(type="simple_array")
*/
private $status;
public function __construct()
{
$this->status = self::DEFAULT_STATUS;
}
public function addFriend(User $user, User $friend): self
{
$userID = $user->getId();
$friendID = $friend->getId();
switch ($userID)
{
case $userID > $friendID:
$this->setUser($friend);
$this->setFriend($user);
break;
case $userID < $friendID:
$this->setUser($user);
$this->setFriend($friend);
break;
case $userID === $friendID:
break;
}
return $this;
}
}
User Entity
/**
* #ORM\Entity()
*/
class User implements UserInterface
{
/**
* Many Users have Many Users.
* The people who I think are my friends.
*
* #ManyToMany(targetEntity="User", mappedBy="myFriends")
*/
private $friendsWithMe;
/**
* Many Users have many Users.
* The people who think that I’m their friend.
*
* #ORM\OneToMany(targetEntity="Friends", mappedBy="user")
*/
private $myFriends;
public function __construct()
{
$this->roles = self::DEFAULT_ROLES;
$this->households = new ArrayCollection();
$this->myFriends = new ArrayCollection();
$this->friendsWithMe = new ArrayCollection();
}
}
The Controller looks like this:
private $entityManager;
private $friends;
private $user;
public function __construct(TokenStorageInterface $tokenStorage, EntityManagerInterface $entityManager)
{
$this->user = $tokenStorage->getToken()->getUser();
$this->friends = new Friends();
$this->entityManager = $entityManager;
}
/**
* #Route("/api/addFriend/{id}", name="addFriend", requirements={"id"="\d+"}, methods={"POST"})
* #ParamConverter("user", class="App:User")
*/
public function addFriend(User $user)
{
$loggedInUser = $this->user;
$add = $this->friends->addFriend($loggedInUser,$user);
$this->entityManager->persist($this->friends);
$this->entityManager->flush();
}
The issue is that When I try to use the controller. It fails at persist() and and the error reads:
Warning: get_class() expects parameter 1 to be object, int given
I believe the issue lies either with the way I am using the user objects in the Friends class Or the way the friend's entity is made. I followed This to show me how to implement the many to many user/Friends relationship initially. Could anyone help guide me in the right direction, please? Thank you very much.
I am making a web app using Symfony 4.
The app has (among others) a User entity, Post entity, and a PostLike entity. A user can create many posts, and a post can have many likes. So PostLike references User and Post. Below is my PostLike entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #ORM\Entity(repositoryClass="App\Repository\PostLikeRepository")
*/
class PostLike
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="postLikes")
* #ORM\JoinColumn(nullable=true)
*/
private $user;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Post", inversedBy="postLikes")
* #ORM\JoinColumn(nullable=true)
*/
private $post;
/**
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $createdAt;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
*/
public function setId($id): void
{
$this->id = $id;
}
/**
* #return mixed
*/
public function getUser()
{
return $this->user;
}
/**
* #param mixed $user
*/
public function setUser($user): void
{
$this->user = $user;
}
/**
* #return mixed
*/
public function getPost()
{
return $this->post;
}
/**
* #param mixed $post
*/
public function setPost($post): void
{
$this->post = $post;
}
public function getCreatedAt()
{
return $this->createdAt;
}
}
When I am on the view page for an individual post, how would I reference whether a user has liked this post in TWIG? This will be the ‘many’ side of the relationship, but I just need one row (if it exists), and I’m not sure how to do this...
TIA.
In the controller you can check whether such PostLike with such user and post exist or not and pass it to the view:
$liked = false;
$postLike = $this->getDoctrine()->getManager()->getRepository('AppBundle:PostLike')->findOneBy(['user'=>$user->getId(),'post'=>$post->getId()]);
if($postLike !== null){
$liked = true;
}
If you want to simply show whether Likes exist you can add a field to the Post entity:
public function hasLikes()
{
return (0 === count($this->likes)) ? false : true;
}
and include in twig something like {% if post.hasLikes %}Liked{% endif %}.
You could do something similar with a count and a badge to show the number of likes.
my question is how to delete entity on the inverse side without going through every association and delete it manually.
<?php
/** #Entity */
class User
{
// ...
/**
* #OneToMany(targetEntity="Address", mappedBy="user")
*/
private $addresses;
// ...
public function __construct() {
$this->addresses = new ArrayCollection();
}
}
/** #Entity */
class Address
{
// ...
/**
* #ManyToOne(targetEntity="User", inversedBy="features")
* #JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
// ...
}
In this example, Address is the owning side, so I can't delete User because foreign key validation will fail. I have to delete Address and then delete User. If I have 10 relationships like these the delete process is painful.
I can create ManyToMany relationship, but this way the Address entity will have users not user and I want addresses to have only one user.
What is the best way to do this?
I hope it's helpful.
Just add cascade to inverse side entity.
/** #Entity */
class User
{
// ...
/**
* #OneToMany(targetEntity="Address", mappedBy="user", cascade={"persist", "remove"})
*/
private $addresses;
// ...
public function __construct() {
$this->addresses = new ArrayCollection();
}
/*
* #return ArrayCollection
*/
public function getAddresses (){
return $this->addresses:
}
/*
* #pram Address $address
*/
public function setAddresses (Address $address){
$this->addresses->add ($address);
}
}
I try to save related entities User and Profile. I use the cascade={"persist"} option. Data saves properly in Database except user_id field in Profile table, its equal to null. When i turn relations profile_id field in User table saves properly. Where is my mistake? Here is my relations:
User entity:
/**
* #ORM\OneToOne(targetEntity="Profile", mappedBy="user", ,cascade={"persist"})
*/
Profile entity:
/**
* #ORM\OneToOne(targetEntity="User", inversedBy="profile", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
Getters & setters:
User:
` /**
* #param Profile $profile
*/
public function setProfile(Profile $profile)
{
$this->profile = $profile;
}
/**
* #return Profile
*/
public function getProfile()
{
return $this->profile;
}`
Profile:
`/**
* #param User $user
*/
public function setUser(User $user)
{
$this->user = $user;
}
/**
* #return User
*/
public function getUser()
{
return $this->user;
}`
This is essentially #skler answer but I couldn't explain myself in comments.
Try doing this in your User.php's setProfile():
public function setProfile(Profile $profile)
{
$this->profile = $profile;
$this->profile->setUser($this);
}
Maybe you add only profile in user: $user->addProfile($profile); and you didn't the viceversa: $profile->addUser($user);
I have a problem while json_encodeing a Entity.
public function jsonvoteAction($id) {
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('KorumAGBundle:AGVote')->findOneById($id);
$response = new Response(json_encode($entity, 200));
$response->headers->set('Content-Type',' application/json');
return $response;
}
This code returns me a the users entity
{"users":{"__isInitialized__":false,"id":null,"nickname":null,"pwd":null,"email":null,"firstname":null,"lastname":null,"poste":null,"addr1":null,"addr2":null,"pc":null,"country":null,"phone":null,"province":null,"acess":null,"site":null,"crew":null,"utilisateur":null}}
And when I var dymp my $entity, it returns both my AGVote and USers entity.
Here is my AGVote Entity
<?php
namespace Korum\AGBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Korum\AGBundle\Entity\AGVote
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class AGVote
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* #ORM\Column(type="text")
*/
private $question;
/**
* #ORM\Column(type="smallint")
*/
private $actif;
/**
* #ORM\ManyToOne(targetEntity="\Korum\KBundle\Entity\Users", cascade={"all"})
*/
public $users;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set question
* Nb : Only AG admin can set a question
* #param text $question
*/
public function setQuestion($question)
{
$this->question = $question;
}
/**
* Get question
*
* #return text
*/
public function getquestion()
{
return $this->question;
}
/**
* Set actif
*
* #param smallint $actif
*/
public function setActif($actif)
{
$this->actif = $actif;
}
/**
* Get actif
*
* #return smallint
*/
public function getActif()
{
return $this->actif;
}
/**
* Set Users
*
* #param Korum\KBundle\Entity\Province $Users
*/
public function setUsers(\Korum\KBundle\Entity\Users $users)
{
$this->users = $users;
}
/**
* Get Users
*
* #return Korum\KBundle\Entity\Users
*/
public function getUsers()
{
return $this->users;
}
}
Does anyone have an idea of what happened ?
I tried to install the JSMSerializerBundle but event with Metadata library at version 1.1.
When I want to clear my cache, it failed with error :
See :
JMSSerializerBundle Installation : Catchable Fatal Error: Argument 1 passed to JMSSerializerBundle\Twig\SerializerExtension::__construct()
By default, json_encode only uses public properties.
So it serialized the only public property of AGVote: $users. The content of $users was an instance of User; which public fields were serialized.
You could work around these by adding a toArray() method to your entities, and then doing json_encode($entity->toArray()), but i highly recommend you to have a look and use the JMSSerializedBundle.