symfony2 filter in manytomany relation - symfony

I have an entity called User that has the following:
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\Column(type="string",length=100)
**/
protected $id_user;
/** #ORM\Column(type="string")
*/
protected $surname;
/**
* #ORM\Column(type="string",length=50)
*/
protected $name;
/**
* #var ArrayCollection $friends
* #ORM\ManyToMany(targetEntity="UniDocs\UserBundle\Entity\User")
* #ORM\JoinTable(name="friends",
* joinColumns={#ORM\JoinColumn(name="friend1", referencedColumnName="id_user")},
* inverseJoinColumns={#ORM\JoinColumn(name="friend2", referencedColumnName="id_user")}
* )
*/
protected $friends;
.
.
.
/**
* Get friends
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getFriends()
{
return $this->friends;
}
.
.
.
}
I need to make a query that gives me the friends of an user which name contain letter 'a' and surname letter 'b' (for example. Those letter are specified on a filter in a web form).
I know I can access all the friends of the registered user using getFriends() method, but... how to filter those friends?

You cannot do that using getters, you need to write a repository method and use that method in order to fetch exactly what you are looking for.
class FriendRepository extends EntityRepository
{
public function findByUserAlphabetical(User $user)
{
// do query with alphabetical stuff
return $query = ...
}
}
Then in your logic:
$friends = $friendRepository->findByUserAlphabetical($user);
$user->setFriends($friends);
Also, you will want to prevent fetching the friends in the original User query, so you can set your annotation fetch to LAZY:
/**
* #var ArrayCollection $friends
* #ORM\ManyToMany(targetEntity="UniDocs\UserBundle\Entity\User", fetch="LAZY")
* #ORM\JoinTable(name="friends",
* joinColumns={#ORM\JoinColumn(name="friend1", referencedColumnName="id_user")},
* inverseJoinColumns={#ORM\JoinColumn(name="friend2", referencedColumnName="id_user")}
* )
*/
protected $friends;

Related

Join columns by referencedColumnName that is not primary key - id

I am rookie in Symfony Doctrine and need some help with Join entities.
Normally Column are joins by primary key ID
/**
* User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="MainBundle\Repository\UserRepository")
* UniqueEntity("email", message="Account with email already exists.")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #var \MainBundle\Entity\PersonDetails
*
* #ORM\ManyToOne(targetEntity="MainBundle\Entity\Person")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="person_details_id", referencedColumnName="id", nullable=true)
* })
*/
private $personDetails = null;
This is ok.
But problem is that I want to Join two columns in Relation OneToOne by id field in User Entity
/**
* User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="MainBundle\Repository\UserRepository")
* UniqueEntity("email", message="Account with email already exists.")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #var \MainBundle\Entity\PersonDetails
*
* #ORM\ManyToOne(targetEntity="MainBundle\Entity\Person")
* #ORM\JoinColumn(name="id", referencedColumnName="user_id", nullable=true)
* })
*/
private $personDetails = null;
When I try to join columns on this way I get error
Missing value for primary key id on MainBundle\Entity\PersonDetails
Is it possible to index other field than id or what I trying to do is impossible?
Thanks guys.
You have mixed up the column-name and the field-name that shall be referenced in your #JoinColumn declaration.
#JoinColumn(name="id", referencedColumnName="user_id")
This way Doctrine looks for a field/property named user_id on your User entity. I guess you want the column in the join-table to be named user_id and the entries being id's of the User entity.
UserDetail
/**
* #ORM\Entity
*/
class UserDetail
{
/**
* #ORM\ManyToOne(
* targetEntity="User",
* inversedBy="details"
* )
* #ORM\JoinColumn(
* name="user_id",
* referencedColumnName="id"
* )
*/
protected $user;
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
/** #ORM\Column() */
protected $key;
/** #ORM\Column() */
protected $value;
public function __construct($key, $value)
{
$this->key = $key;
$this->value = $value;
}
User
class User
{
/**
* #ORM\Id()
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToMany(
* targetEntity="UserDetail",
* mappedBy="user",
* cascade={
* "persist",
* "remove",
* "merge"
* },
* orphanRemoval=true
* )
*/
protected $details;
public function __construct()
{
$this->details = new ArrayCollection();
}
public function addDetail(UserDetail $detail)
{
$detail->setUser($this);
$this->details->add($detail);
return $this;
}
Now if you add a detail to your User like this and persist/flush afterwards:
$user->addDetail(new UserDetail('Height', '173cm'));
This will result in a join-colum in the user_detail table that looks like this:
| key | value | user_id |
|---------------|-----------|---------|
| Height | 173cm | 1 |
Citing Doctrine documentation:
It is not possible to use join columns pointing to non-primary keys.
Doctrine will think these are the primary keys and create lazy-loading
proxies with the data, which can lead to unexpected results. Doctrine
can for performance reasons not validate the correctness of this
settings at runtime but only through the Validate Schema command.
I had the same problem, I solved it by performing the mapping only to fields that are primary key. If I needed to get the related entities by other fields, I implemented methods in the Entity repository.

symfony2 - add value to protected object

How can I set the protected object user? After filling the form i have to add user object with current user data (for example like saving comments). I tried something like that:
if ($form->isValid()) {
$comment = $form->getData();
$comment->user = $this->contextSecurity->getToken()->getUser();
$this->model->save($comment);
}
And i've got this error
FatalErrorException: Error: Cannot access protected property AppBundle\Entity\Comment::$user in /home/AppBundle/Controller/CommentsController.php line 184
Here is my Comment entity:
class Comment
{
/**
* Id.
*
* #ORM\Id
* #ORM\Column(
* type="integer",
* nullable=false,
* options={
* "unsigned" = true
* }
* )
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #var integer $id
*/
private $id;
/**
* Content.
*
* #ORM\Column(
* name="content",
* type="string",
* length=250,
* nullable=false
* )
* #Assert\NotBlank(groups={"c-default"})
* #Assert\Length(min=3, max=250, groups={"c-default"})
*
* #var string $content
*/
private $content;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="comments")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
*/
protected $user;
I'm using Symfony2.3. Any help will be appreciated.
You can't modify protected properties from outside of the object. You need a public property or a setter for that.
class Comment
{
// ...
public function setUser(User $user)
{
$this->user = $user;
}
}
And in a controller you can write:
$comment->setUser($this->getUser());
This question is not related to Symfony2, at first you should read about php types, especially about objects. read here and then here
You should understand how Visibility works. After that you will understand that access to protected/private properties of the object is only available from the object itself, so you need to create public method
setUser($user) {
$this->user = $user;
}
I always use protected, If i want edit variable or take the value, I use the getter and setter:
public function setUser($user) {
$this->user = $user;
}
public function getUser(){
return $this->user;
}

symfony entity catching up inversed Values in many to many

I'm trying to setup a many to many between fos Userbundle and my own group bundle so that I can group users. this is working fine. I can set a new group and can add as many users to this group as I like to. But when I want to check if a user is in a group, I get a Index join Column error. I think I didn't understand the usage of manytomany the correct way so it would be nice if you can help me getting the point.
My entities look like:
User:
class User extends BaseUser
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $usergroups;
//....//
And my Group Entity looks like:
/**
* #ORM\ManyToMany(targetEntity="PrUserBundle\Entity\User", inversedBy="id")
* #ORM\JoinColumn(name="id", referencedColumnName="id")
* #var user
*/
private $user;
//....
/**
* Add user
*
* #param \PrUserBundle\Entity\User $user
* #return Lieferanten
*/
public function addUser(\PrUserBundle\Entity\User $user)
{
$this->user[] = $user;
return $this;
}
/**
* Remove user
*
* #param \PrUserBundle\Entity\User $user
*/
public function removeUser(\PrUserBundle\Entity\User $user)
{
$this->user->removeElement($user);
}
/**
* Get user
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUser()
{
return $this->user;
}
When I try to catch all users in a group, I get an error:
$group=$em->getRepository('PrGroupBundle:Group')->findAll();
var_dump($lfr[0]->getUser()->getId());
I guess I missunderstood how to handle the bidirectional manytomany. Or can I use a manytoone also?

how to check whether foreign key is working or not in symfony2 with doctrine

I have followed One-to-Many relation not working and created a one to many relationship
i have a users table where i have following fields
- id(primary key)
- name
- pwd
i have attachments table where user can upload more than one file i.e one user_id contains multiple files
- id
- user_id(foreignkey)
- path
my user entity contains the following code
namespace Repair\StoreBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* users
* #ORM\Entity(repositoryClass="Repair\StoreBundle\Entity\usersRepository")
*/
class users
{
/**
* #var integer
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
--some code --
/**
* #ORM\OneToMany(targetEntity="attachments", mappedBy="user_id")
*/
private $attachments;
public function __construct()
{
$this->attachments= new ArrayCollection();
}
/**
* Add attachments
*
* #param \Repair\StoreBundle\Entity\attachments $attachments
* #return users
*/
public function addAttachment(\Repair\StoreBundle\Entity\attachments $attachments)
{
$this->attachments[] = $attachments;
return $this;
}
/**
* Remove attachments
*
* #param \Repair\StoreBundle\Entity\attachments $attachments
*/
public function removeAttachment(\Repair\StoreBundle\Entity\attachments $attachments)
{
$this->attachments->removeElement($attachments);
}
/**
* Get attachments
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getAttachments()
{
return $this->attachments;
}
this is my attachments entity
namespace Repair\StoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* attachments
*/
class attachments
{
-- some code for id--
private $id;
/**
* #var integer
* #ORM\Column(name="user_id", type="integer", nullable=false)
* #ORM\ManyToOne(targetEntity="users", inversedBy="users")
* #ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
*/
protected $userId;
public function getId()
{
return $this->id;
}
/**
* Set userId
* #param integer $userId
* #return attachments
*/
public function setUserId($userId)
{
$this->userId = $userId;
return $this;
}
/**
* Get userId
*
* #return integer
*/
public function getuserId()
{
return $this->userId;
}
--Some code for paths --
}
It is not displaying any errors
but how to know whether the foriegn key is set or not i went to phpmyadmin and checked the indexes it only shows the primary keys.please say whether i did correct or not and how to check whether foreign key is set or not
problem is in your annotations. In your attachment entity you should have annotation like this.
* #ORM\ManyToOne(targetEntity="users", inversedBy="annotations")
you don't have to have join column annotation. But if you want to have it there, it should look like this.
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
Also it shouldn't be called user_id but user, because doctrine takes it as whole entity.

Create relationnal entitiy on Symfony 2

I would like to save my users search on my website. Thaht's why i have a Class User and i would like to create Search Class.
I have done that :
class Search
{
public function __construct()
{
$this->searched_date = new \Datetime();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
private $id;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="test\UserBundle\Entity\User")
*/
private $user;
/**
* #ORM\Column(name="termsearch", type="string", length=255, nullable="true")
*/
private $termsearch;
/**
* #ORM\Column(name="goodtitle", type="string", length=255, nullable="true")
*/
private $goodtitle;
/**
* #ORM\Column(name="searched_date", type="datetime")
*/
private $searched_date;
/**
* Set termsearch
*
* #param text $termsearch
*/
public function setTermsearch($termsearch)
{
$this->termsearch = $termsearch;
}
/**
* Get termsearch
*
* #return text
*/
public function getTermsearch()
{
return $this->termsearch;
}
/**
* Set searched_date
*
* #param datetime $searchedDate
*/
public function setSearchedDate($searchedDate)
{
$this->searched_date = $searchedDate;
}
/**
* Get searched_date
*
* #return datetime
*/
public function getSearchedDate()
{
return $this->searched_date;
}
/**
* Set user
*
* #param test\UserBundle\Entity\User $user
*/
public function setUser(\test\UserBundle\Entity\User $user)
{
$this->user = $user;
}
/**
* Get user
*
* #return test\UserBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set goodtitle
*
* #param text $goodtitle
*/
public function setGoodtitle($goodtitle)
{
$this->goodtitle = $goodtitle;
}
/**
* Get goodtitle
*
* #return text
*/
public function getGoodtitle()
{
return $this->goodtitle;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
And i would like to insert like that :
$em = $this->getDoctrine()->getEntityManager();
$user = $em->getRepository('TestUserBundle:User')->find($currentuser->getID());
$search = new Search();
$search->setUser($user);
$search->setTermsearch($termsearch);
$search->setGoodtitle($goodtitle);
$em->persist($search);
$em->flush();
Unfortunately i have this error :
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens (500 Internal Server Error)
And in the stack we can found that :
INSERT INTO s_search (user_id, termsearch, goodtitle, searched_date) VALUES (?, ?, ?, ?) ({"1":"c2c","2":"C2C Down The Road","3":{"date":"2012-10-31 00:18:47","timezone_type":3,"timezone":"Europe\/Paris"}})
I don't know how i can create this class Search...
Thank for for you help !
Remove #ORM\Id from the $user as #ManyToOne mapping reference does not require a type. See Doctrine's Annotation Reference for details. Doctrine takes care of the correct column type to hold the reference to another entity.
Make also sure that your User query really returns a valid $user. If it's possible that Search does not have $user, use #JoinColumn annotation to claim the column nullable. See another SO question Doctrine 2 can't use nullable=false in manyToOne relation?

Resources