Query builder: multiple AND act like an OR - symfony

I have a many to many relation between entities Content and Filter.
I would like to get all Contents which have the filters "1", "2" AND "3" (all three). My query gives me results as if I would use "OR, because I get a lot of contents which have only one of the three Filter.
My query:
public function getContentByFilters($categ, $filter, $filter2, $filter3){
$query = $this->createQueryBuilder('c')
->leftJoin('c.filterfilter', 'f')
->where('f.idfilter = :filter_idfilter')
->setParameter('filter_idfilter', $filter)
->andWhere('f.idfilter = :filter_idfilter')
->setParameter('filter_idfilter', $filter2)
->andWhere('f.idfilter = :filter_idfilter')
->setParameter('filter_idfilter', $filter3)
->andWhere('c.contentCategorycontentCategory = ?2')
->setParameter(2, $categ)
->getQuery()->getResult();
return $query;
}
Entity Content:
/**
* Content
*
* * #ORM\Entity(repositoryClass="loic\ContentBundle\Entity\ContentRepository")
* #ORM\Table(name="content", uniqueConstraints={#ORM\UniqueConstraint(name="idcontent_UNIQUE", columns={"idcontent"})}, indexes={#ORM\Index(name="user_id", columns={"user_id"}), #ORM\Index(name="fk_content_content_category1_idx", columns={"content_category_idcontent_category"})})
*/
class Content
{
/**
* #var integer
*
* #ORM\Column(name="idcontent", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idcontent;
.............
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="loic\FilterBundle\Entity\Filter", inversedBy="contentcontent")
* #ORM\JoinTable(name="content_has_filter",
* joinColumns={
* #ORM\JoinColumn(name="content_idcontent", referencedColumnName="idcontent")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="filter_idfilter", referencedColumnName="idfilter")
* }
* )
*/
private $filterfilter;
/**
* Constructor
*/
public function __construct()
{
$this->contentLinked = new \Doctrine\Common\Collections\ArrayCollection();
$this->filterfilter = new \Doctrine\Common\Collections\ArrayCollection();
$this->creationDate = new \DateTime();
}
.........
/**
*
* #return the \Doctrine\Common\Collections\Collection
*/
public function getFilterfilter() {
return $this->filterfilter;
}
/**
*
* #param
* $filterfilter
*/
public function setFilterfilter($filterfilter) {
$this->filterfilter = $filterfilter;
return $this;
}
}
Entity Filter:
use Doctrine\ORM\Mapping as ORM;
/**
* Filter
*
* * #ORM\Entity(repositoryClass="loic\FilterBundle\Entity\FilterRepository")
* #ORM\Table(name="filter", uniqueConstraints={#ORM\UniqueConstraint(name="idfilter_UNIQUE", columns={"idfilter"})}, indexes={#ORM\Index(name="fk_filter_filter_category1_idx", columns={"filter_category_idfilter_category"})})
*/
class Filter
{
/**
* #var integer
*
* #ORM\Column(name="idfilter", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idfilter;
............
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="loic\ContentBundle\Entity\Content", mappedBy="filterfilter")
*/
private $contentcontent;
.....
/**
* Constructor
*/
public function __construct()
{
$this->contentcontent = new \Doctrine\Common\Collections\ArrayCollection();
$this->user = new \Doctrine\Common\Collections\ArrayCollection();
$this->status = 1;
}
......
/**
*
* #return the \Doctrine\Common\Collections\Collection
*/
public function getContentcontent() {
return $this->contentcontent;
}
/**
*
* #param
* $contentcontent
*/
public function setContentcontent($contentcontent) {
$this->contentcontent = $contentcontent;
return $this;
}

Since you want to check for 3 filters, you need to JOIN 3 times as well. It is as if you had 3 different ManyToMany relationships and only want one row, that fits 3 specific requirements - only difference is, that you join the same table. Untested, but it should work like this
$query = $this->createQueryBuilder('c')
->join('c.filterfilter', 'f1')
->join('c.filterfilter', 'f2')
->join('c.filterfilter', 'f3')
->where('f1.idfilter = :filter_idfilter1')
->andWhere('f2.idfilter = :filter_idfilter2')
->andWhere('f3.idfilter = :filter_idfilter3')
->andWhere('c.contentCategorycontentCategory = :category')
->setParameters(array(
'filter_idfilter1' => $filter,
'filter_idfilter2' => $filter2,
'filter_idfilter3' => $filter3,
'category' => $categ,
))
->getQuery()->getResult();
Inner join is probably better as you only want rows, that do fulfill these requirements. Also be aware, that using too many joins is usually considered bad practice and may slow down performance. Preferred solution is usually to construct a specific view instead of multiple joins.

Related

I get friends and all other users when trying to load only friends of the current user

I am trying to load friends of a specific user after asking why I get null values of the friend of the user data it was responded that it was because of the lazy loading. So I was advised to add JOIN and I admit this was a miss from my side. But after adding the JOIN I get the data of the friend in the result and then I receive all the users from my users table for which I have not asked.
I have already tried removing the myuser from the SELECT, but this way I get the lazy loading problem again. I have tried LEFT JOIN (I admit it was dumb try from my side). But how can I correct this when there is no ON in the Doctrine Query Language.
My Entity(Friends):
class Friends
{
/**
* #ORM\Id()
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="myfriends")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
*/
private $friendsWithMe;
/**
* #ORM\Id()
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="friendof")
* #ORM\JoinColumn(name="friend_id", referencedColumnName="id", nullable=false)
*/
private $afriendof;
/**
* #var integer
*
* #ORM\Column(name="status", type="smallint")
*/
private $status;
/**
* #return User
*/
public function getFriendsWithMe()
{
return $this->friendsWithMe;
}
/**
* #param mixed $friendsWithMe
*/
public function setFriendsWithMe($friendsWithMe)
{
$this->friendsWithMe = $friendsWithMe;
}
/**
* #return User
*/
public function getAfriendof()
{
return $this->afriendof;
}
/**
* #param mixed $afriendof
*/
public function setAfriendof($afriendof)
{
$this->afriendof = $afriendof;
}
/**
* #return integer
*/
public function getStatus()
{
return $this->status;
}
/**
* #param integer $status
*/
public function setStatus($status)
{
$this->status = $status;
}
}
My Entity(User):
class User implements UserInterface
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
public function __construct()
{
$this->userPosts = new ArrayCollection();
$this->myfriends = new ArrayCollection();
$this->friendof = new ArrayCollection();
}
/**
* #var
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Friends", mappedBy="afriendof")
*/
private $friendof;
/**
* #var
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Friends", mappedBy="friendsWithMe")
*/
private $myfriends;
My Repository(FriendsRepository):
public function personalFriends($userId){
$em = $this->getEntityManager();
$result = $em->createQuery('SELECT friends, myuser FROM AppBundle\Entity\Friends friends
INNER JOIN AppBundle\Entity\User myuser WHERE friends.friendsWithMe = :userId AND friends.status = 1');
$result->setParameter('userId', $userId);
return $result->getResult();
}
The place where I call the repository:
public function indexAction(Request $request)
{
$user = $this->get('security.token_storage')->getToken()->getUser();
$userId = $user->getId();
$friends = $this->getDoctrine()->getRepository(Friends::class)->personalFriends($userId);
dump($friends);
exit();
Results that I get now:
https://pastebin.com/2M4SYTLb
Results that I expect:
https://pastebin.com/BxsC9QbE
Hope I understand your problem.
But from what I see you are asking for the data of the friends AND the data of the users when you are doing 'SELECT friends, myuser.
Try only selecting friends
Like this:
SELECT friend FROM AppBundle\Entity\Friends friend INNER JOIN AppBundle\Entity\User user WHERE friend.friendsWithMe = :userId AND friend.status = 1
Then you'll only have as a result an array of Friends.
If there is still a problem you can add fetch="EAGER" so it wont be "LAZY"
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="myfriends", fetch="EAGER")

findBy() foreignKey is not working

There is a relationship between the rubric and brand table (Many rubric to One brand).
Here is my code
$dbChoices = $this->getConfigurationPool()
->getContainer()
->get('Doctrine')
->getManager()
->getRepository('RibambelMainBundle:RubricMenu')
->findBy(array('brand_id' => 2));
Everytime this part is run, I got the following error:
Unrecognized field: brand_id
The brand_id column is found in the rubric table.
Anyone who can help me with this or show me another way of doing it?
class RubricMenu
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="Title", type="string", length=255)
*/
private $title;
/**
* #var int
*
* #ORM\Column(name="position", type="integer")
*/
private $position;
/**
* #ORM\ManyToOne(targetEntity="Brand")
* #ORM\JoinColumn(name="brand_id", nullable=false)
*/
private $brand;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $title
*
* #return RubricMenu
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set position
*
* #param integer $position
*
* #return RubricMenu
*/
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
* Get position
*
* #return int
*/
public function getPosition()
{
return $this->position;
}
/**
* Set brand
*
* #param \Ribambel\MainBundle\Entity\Brand $brand
*
* #return RubricMenu
*/
public function setBrand(\Ribambel\MainBundle\Entity\Brand $brand = null)
{
$this->brand = $brand;
return $this;
}
/**
* Get brand
*
* #return \Ribambel\MainBundle\Entity\Brand
*/
public function getBrand()
{
return $this->brand;
}
}
Searching by a foreign key simply does not make sense from an object point of view. brand_id is not a field of your RubricMenu entity, brand is.
If you have a Brand entity, then you can use findBy (or the magic method findByBrand) like this: (with $myBrand an instance of Brand)
$repository->findBy(['brand' => $myBrand]);
// OR
$repository->findByBrand($myBrand);
If you simply have the id of your target entity, you can use the IDENTITY DQL function but in that case you cannot use findBy directly as it expects a valid field name. Thus, you will need to add a method in your RubricMenu repository. Your method could look like this:
public function findByBrandId($brandId)
{
$qb = $this->createQueryBuilder('rm');
$qb->where('IDENTITY(rm.brand) = :brandId')
->setParameter('brandId', $brandId);
return $qb->getQuery()->getResult();
}
On a side note, as pointed out by #l.g.karolos's answer, doing
$repository->findBy(['brand' => $brandId]);
// OR
$repository->findByBrand($brandId);
will also work as the findBy method internals will be able to resolve that the given parameter is an ID of a Brand entity, thus it will produce the same query as if you had given the corresponding Brand instance.
Based on your entity you should do the following.
$dbChoices = $this->getConfigurationPool()
->getContainer()
->get('Doctrine')
->getManager()
->getRepository('RibambelMainBundle:RubricMenu')
->findBy(array('brand' => 2));
i thing you can do:
$dbChoices = $this->getConfigurationPool()
->getContainer()
->get('Doctrine')
->getManager()
->getRepository('RibambelMainBundle:RubricMenu')
->findBy(array('brand' => $brand));
if you have $brand object (...\Entity\Brand)
Example on https://www.wanadev.fr/56-comment-realiser-de-belles-requetes-sql-avec-doctrine/ :
$user = …;
$category = …;
$em = $this->container->get("doctrine.orm.default_entity_manager");
$entities = $em->getRepository(MyClass::class)->findBy([
"user" => $user,
"category" => $category,
]);

Symfony 2 - findall() too many DB queries

why Symfony2 performs 40 DB queries if I use following code:
$em = $this->getDoctrine()->getManager();
$records = $em->getRepository('MyWebBundle:Highlight')->findAll();
I thought that findAll() method returns only all items from Highlight entity and associations to other entities replaces Proxy objects. But now findAll() method gettings all associations entities.
Do you know where is the problem ?
indexAction
public function indexAction() {
$em = $this->getDoctrine()->getManager();
$records = $em->getRepository('MyWebBundle:Highlight')->findAll();
$csrf = $this->get('security.csrf.token_manager');
$token = $csrf->refreshToken(self::FORM_TOKEN_ID);
$params = array(
"data" => array(
"all" => $records,
),
"token" => $token->getValue(),
"static" => array(
"add" => $this->generateUrl("admin_highlight_add"),
"edit" => $this->generateUrl("admin_highlight_edit"),
"del" => $this->generateUrl("admin_highlight_del"),
),
);
$ser = $this->get('jms_serializer');
$jsonContent = $ser->serialize($params, 'json');
return array('jsonContent' => $jsonContent);
}
Highlight entity
namespace My\WebBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
/**
* Highlight
*
* #JMS\ExclusionPolicy("none")
* #ORM\Table()
* #ORM\Entity(repositoryClass="My\WebBundle\Entity\HighlightRepository")
*/
class Highlight {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="abbreviation", type="string", length=8, unique=true)
*/
private $abbreviation;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=80, nullable=true)
*/
private $description;
/**
* #var string
*
* #ORM\Column(name="color", type="string", length=7)
*/
private $color;
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="Goods", mappedBy="highlight")
*/
private $goods;
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="Calibration", mappedBy="highlight")
*/
private $calibrations;
/**
* Constructor
*/
public function __construct() {
$this->goods = new \Doctrine\Common\Collections\ArrayCollection();
$this->calibrations = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set abbreviation
*
* #param string $abbreviation
* #return Highlight
*/
public function setAbbreviation($abbreviation) {
$this->abbreviation = $abbreviation;
return $this;
}
/**
* Get abbreviation
*
* #return string
*/
public function getAbbreviation() {
return $this->abbreviation;
}
/**
* Set description
*
* #param string $description
* #return Highlight
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription() {
return $this->description;
}
/**
* Set color
*
* #param string $color
* #return Highlight
*/
public function setColor($color) {
$this->color = $color;
return $this;
}
/**
* Get color
*
* #return string
*/
public function getColor() {
return $this->color;
}
/**
* Add goods
*
* #param \My\WebBundle\Entity\Goods $goods
* #return Highlight
*/
public function addGood(\My\WebBundle\Entity\Goods $goods) {
$this->goods[] = $goods;
return $this;
}
/**
* Remove goods
*
* #param \My\WebBundle\Entity\Goods $goods
*/
public function removeGood(\My\WebBundle\Entity\Goods $goods) {
$this->goods->removeElement($goods);
}
/**
* Get goods
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGoods() {
return $this->goods;
}
/**
* Add calibrations
*
* #param \My\WebBundle\Entity\Calibration $calibrations
* #return Highlight
*/
public function addCalibration(\My\WebBundle\Entity\Calibration $calibrations) {
$this->calibrations[] = $calibrations;
return $this;
}
/**
* Remove calibrations
*
* #param \My\WebBundle\Entity\Calibration $calibrations
*/
public function removeCalibration(\My\WebBundle\Entity\Calibration $calibrations) {
$this->calibrations->removeElement($calibrations);
}
/**
* Get calibrations
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCalibrations() {
return $this->calibrations;
}
}
Highlight repository is empty
I think the problem comes from the serializer. Since you serializer highliths, each of them has their properties serialized as well which means that lazy query will be performed to retieved Goods which will be also serialized.
You should then prevent this behaviour by adding annotations to highlight's goods property as this
use ...
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Exclude;
/**
* ...
* #ExclusionPolicy("none")
*/
class Highlight
{
/**
* ...
* #Exclude
*/
private $goods;
}
You can have further details about exclusion stratigies from JMSSerializer doc
findAll itself does not perform many queries. Queries are executed when you access related entity via getters. As relation are not fetched eagerly, they first time are fetched when you are acessing them.
I think serializer access all children to send your object.
See Doctrine documentation
Whenever you have a managed entity instance at hand, you can traverse
and use any associations of that entity that are configured LAZY as if
they were in-memory already. Doctrine will automatically load the
associated objects on demand through the concept of lazy-loading.
To prevent this either disable children serialization or use fetch EAGER or build a DQL query, which prefetch all the children alongside with parents, like (just sample, not valid DQL)
SELECT Highlight, Good, Calibration
FROM Highlights Highlight
LEFT JOIN Highlight.googs Good
LEFT JOIN Goog.calibrations Calibration
WHERE ...

UniqueEntity on fosuserbundle field does not work

In my class I've got a UniqueEntity limitation on the "user" field (originally on the combination of "user" and "name"), which is derived from the fosuserbundle, if I put the constraint on "name" for example the constraint does its job and I get an error saying it's not unique. This does not happen on the user field however, I get no error and the entity is added to my database. Could someone point out the mistake I made?
namespace CB\DefaultBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* CustomList
*
* #ORM\Table()
* #ORM\Entity
* #UniqueEntity("user")
*/
class CustomList
{
/**
* #var integer
*
* #ORM\Column(name="Id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\NotBlank()
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255, nullable=true)
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="customlists")
* #ORM\JoinColumn(name="user_id", referencedColumnName="Id")
*/
private $user;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="CB\DefaultBundle\Entity\Site", inversedBy="customlists")
* #ORM\JoinTable(name="customlist_site",
* joinColumns={
* #ORM\JoinColumn(name="customlist_id", referencedColumnName="Id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="site_id", referencedColumnName="Id")
* }
* )
*/
private $sites;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return CustomList
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set description
*
* #param string $description
* #return CustomList
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set category
*
* #param \CB\DefaultBundle\Entity\Category $category
* #return CustomList
*/
public function setCategory(\CB\DefaultBundle\Entity\Category $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return \CB\DefaultBundle\Entity\Category
*/
public function getCategory()
{
return $this->category;
}
/**
* Set user
*
* #param \CB\DefaultBundle\Entity\User $user
* #return CustomList
*/
public function setUser(\CB\DefaultBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \CB\DefaultBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Constructor
*/
public function __construct()
{
$this->sites = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add sites
*
* #param \CB\DefaultBundle\Entity\Site $sites
* #return CustomList
*/
public function addSite(\CB\DefaultBundle\Entity\Site $sites)
{
$this->sites[] = $sites;
return $this;
}
/**
* Remove sites
*
* #param \CB\DefaultBundle\Entity\Site $sites
*/
public function removeSite(\CB\DefaultBundle\Entity\Site $sites)
{
$this->sites->removeElement($sites);
}
/**
* Get sites
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getSites()
{
return $this->sites;
}
}
Ok, I found my error, It was in my controller logic:
...
$list = new CustomList();
$form = $this->createForm(new CustomListType(), $list);
$form->submit($request);
$list = $form->getData();
$validator = $this->get('validator');
$errors = $validator->validate($list);
var_dump((string) $errors);
if ($form->isValid()){
$em = $this->getDoctrine()->getManager();
//set current user as user-value of this list
$list->setUser($this->getUser());
$em->persist($list);
$em->flush();
//prepare the response, e.g.
$response = array("code" => 100, "success" => true);
//you can return result as JSON , remember to 'use' Response!
return new Response(json_encode($response));
...
As you can see I set the user AFTER the form has been validated, meaning it would always validate the null values, as seen in the documentation here: UniqueEntity the default value of ignoreNull is true, meaning it would always pass the test.
Moving the $list->setUser($this->getUser()); line before my validation of the form fixed this problem!

Little innerJoin-Query

Old Query in symfony 1.4 and doctrine 1.2
$user = Doctrine_Query::create()
->from('User.u')
->innerJoin('u.State s')
->where('u.id = ?', $id)
->andWhere('u.state_id = ?', $state_id)
->fetchOne();
Now my Query in symfony2:
$repository = $this->getDoctrine()
->getRepository('FrontendAccountBundle:User');
$user = $repository->findBy(array(
'activationId' => $activation_id),
array('state' => 3));
My error is comming up:
Unrecognized field: state
What is the problem?
Edit: reformatted code
Update
User-Entity:
namespace Frontend\AccountBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity
*/
class User implements UserInterface, \Serializable
{
/**
* #var string
*
* #ORM\Column(name="activation_id", type="string", length=255, nullable=true)
*/
private $activationId;
/**
* #var \State
*
* #ORM\ManyToOne(targetEntity="State")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="state_id", referencedColumnName="id")
* })
*/
private $state;
/**
* Set activationId
*
* #param string $activationId
* #return User
*/
public function setActivationId($activationId)
{
$this->activationId = $activationId;
return $this;
}
/**
* Get activationId
*
* #return string
*/
public function getActivationId()
{
return $this->activationId;
}
/**
* Set state
*
* #param \Frontend\AccountBundle\Entity\State $state
* #return User
*/
public function setState(\Frontend\AccountBundle\Entity\State $state = null)
{
$this->state = $state;
return $this;
}
/**
* Get state
*
* #return \Frontend\AccountBundle\Entity\State
*/
public function getState()
{
return $this->state;
}
public function __construct()
{
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
/**
* #inheritDoc
*/
public function getUsername()
{
return $this->email;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
) = unserialize($serialized);
}
}
User-Entity:
namespace Frontend\AccountBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* State
*
* #ORM\Table(name="state")
* #ORM\Entity
*/
class State
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="state", type="string", length=255, nullable=false)
*/
private $state;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255, nullable=false)
*/
private $description;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set state
*
* #param string $state
* #return State
*/
public function setState($state)
{
$this->state = $state;
return $this;
}
/**
* Get state
*
* #return string
*/
public function getState()
{
return $this->state;
}
/**
* Set description
*
* #param string $description
* #return State
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
}
The problem is that the variable in the User entity is "state" not "stateId". You must always use the names from the entity, not the database. The join from User to State also needs to be done since the stateId is in the State entity.
When joins are needed you are probably better off using queryBuilder or DQL.
Here's a post about joins in Doctrine 2 queryBuilder: doctrine 2 query builder and join tables
Here's the documentation from the Symfony Book for Doctrine: http://symfony.com/doc/current/book/doctrine.html#entity-relationships-associations
Here's an example from my project that is very similar to your problem:
$uid = 2;
$rep = $this->getDoctrine()->getRepository('DevondevTrackRTimeBundle:Activity');
$q = $rep->createQueryBuilder('a')
->select ('a.activityId, a.startTime, a.endTime, u.username')
->join('a.login','u')
->where('u.id = :uid')
->setParameter('uid', $uid)
->getQuery();
$acts = $q->getResult();
If I didn't need anything from the user table the query could be written as
$uid = 2;
$rep = $this->getDoctrine()->getRepository('DevondevTrackRTimeBundle:Activity');
$q = $rep->createQueryBuilder('a')
->where('a.login = :uid')
->setParameter('uid', $uid)
->getQuery();
$acts = $q->getResult();
This is your query reworked in the same way:
$rep = $this->getDoctrine()->getRepository('FrontendAccountBundle:User');
$q = $rep->createQueryBuilder('u')
->join('u.state','s')
->where ('u.id = :uid')
->andWhere ('s.stateId = :sid')
->setParameters(array('uid' => $id, 'sid' => $state_id))
->getQuery();
$user = $q->getSingleResult();
Thanks to Peter to light me up a little bit!!!
If you don't want again a the stupid solution from symfony2(-docs) and doctrine2, because you need much more code than in symfony1.4, like that way http://symfony.com/doc/current/book/doctrine.html#joining-to-related-records. Try my solution.
Here is the result.
$em = $this->getDoctrine()->getEntityManager();
$user = $em->createQuery('SELECT u FROM FrontendAccountBundle:User u
INNER JOIN FrontendAccountBundle:State s
WHERE
u.activation_id=:activation_id
and
u.state=:state_id
')
->setParameter('activation_id', $activation_id)
->setParameter('state_id', 3)
->getSingleResult();

Resources