How convert my SQL statement to Doctrine QueryBuilder? - symfony

SELECT * FROM PropertyRequest p JOIN leads l WHERE p.lead_id= l.id
How can I write this sql statement with doctrine2 querybuilder? I'm trying with this
$qb = $this->createQueryBuilder('p')
->Join('p.lead', 'm')
->Where('m.id = :lead')
->setParameter(':lead', $lead);
return $qb->getQuery()->getResult();
but doesn't work

I suspect from here on, that you defined the lead_id as "lead" in the entity p. My answer is based on these assumptions.
You can then use this statement to perform the join
$qb = $this->createQueryBuilder('p')
->innerJoin('p.lead', 'm', 'WITH', 'p.lead = m.id')
->Where('m.id = :lead')
->setParameter(':lead', $lead);
return $qb->getQuery()->getResult();
If this does not work you need to provide a error message an probably the definition of both entities as well.

this is the way i make my queries.
//---Controller
$em = $this->getDoctrine()->getRepository('SomeBundle:SomeEntity');
$query = $em->createQueryBuilder('p')
->select("p")
->leftJoin("p.lead", "c")
->where("m.id = :lead")
->setParameter(":lead", $lead);
return $query->getResult();
//---Entity
<?php
namespace Some\SomeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Some\SomeBundle\Entity\SomeEntity
*
* #ORM\Table(name="sometable")
* #ORM\Entity
*/
class SomeEntity
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=75, nullable=false)
*/
private $name;
/**
* #var SomeOtherEntity
*
* #ORM\ManyToOne(targetEntity="SomeOtherEntity")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="lead", referencedColumnName="onelead")
* })
*/
private $lead;
/**
* Set lead
*
* #param Some\SomeBundle\Entity\SomeOtherEntity $lead
* #return SomeOtherEntity
*/
public function setLead(\Some\SomeBundle\Entity\SomeOtherEntity $lead = null)
{
$this->lead = $lead;
return $this;
}
/**
* Get lead
*
* #return Some\SomeBundle\Entity\SomeOtherEntity
*/
public function getLead()
{
return $this->lead;
}
}
Does it throw an error?

Related

Query builder: multiple AND act like an OR

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.

How to fetch data from many to many relation ship third table using symfony2 doctrine DQL

1)Category Entity:
/**
* Category
*
* #ORM\Table(name="category")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
*/
class Category {
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="categoryname", type="string")
*/
protected $categoryname;
/**
* #ORM\ManyToMany(targetEntity="Tag", inversedBy="categories")
*/
protected $tags;
/**
* #return ArrayCollection
*/
public function __construct(){
$this->tags = new ArrayCollection();
}
2) Tag Entity:
/**
* Tag
* #ORM\Table(name="tag")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TagRepository")
*/
class Tag {
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
protected $id;
/**
*
* #var string
*
*#ORM\Column(name="tagname", type="string")
*/
protected $tagname;
/**
* #ORM\ManyToMany(targetEntity="Category", mappedBy="tags")
*/
protected $categories;
/**
* #return ArrayCollection
*/
public function __construct(){
$this->categories = new ArrayCollection();
}
I am using below dql query: getting third table data form database,But i stuck to that getting third table data:
$categoryId = $request->request->get('cat_id');
$repository = $em->getRepository('AppBundle:Tag');
$tags = $repository->createQueryBuilder('t')
->innerJoin('t.categories', 'c')
->where('c.id = :category_id')
->setParameter('category_id', $categoryId)
->getQuery()->getResult();
How to get third table(category_tag) data from database using DQl query:
Thanks for advance...
I think you should add an * #JoinTable annotation the $tags attribute in the Category entity, like this:
/**
* #ORM\ManyToMany(targetEntity="Tag", inversedBy="categories")
* #ORM\JoinTable(name="category_tag")
*/
protected $tags;
Check documentation for Doctrine Many-toMany here: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-bidirectional.
If what you want the query to result is an array with the pairs of ids that have the many-to-may relation, then your query should look like this:
$tags = $repository->createQueryBuilder('t')
->select('c.id as categoryId, t.id as tagId')
->innerJoin('t.categories', 'c')
->where('c.id = :category_id')
->setParameter('category_id', $categoryId)
->getQuery()
->getResult();
Hope this helps! :)

Doctrine and join result type

I've 2 simple tables with many-to-one mono directional relations:
class Event extends BaseEvent
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\ManyToOne(targetEntity="Rposition")
* #ORM\JoinColumn(name="owner", referencedColumnName="id",onDelete="CASCADE", nullable=false )
**/
private $owner;
....
and the origin of the owner field class:
class Rposition
{
/**
* #var integer
*
* #ORM\Column(name="id", type="string", length=36)
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
*
*
* #ORM\Column(name="scenario", type="string", length=255, nullable=false)
*/
private $scenario;
both class having the right getter/setter and a __tostring()
I need to implements a query like this:
public function findAllByScenario($scenario) {
$q = $this->getEntityManager()->createQuery("SELECT e , r.scenario , r.id
FROM LapoMymeBundle:Event e
JOIN LapoMymeBundle:Rposition r
WITH e.owner = r.id
WHERE r.scenario = :scenario
ORDER BY e.start ASC, e.end ASC
")->setParameter('scenario', $scenario);
try {
return $q->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
-is it the right way to making a join and sending back result from it?
-what are the right way for fetching the fields from the array of objects?
something like that's:
$events=$this->getDoctrine()->getManager()
->getRepository('LapoMymeBundle:Event')->findAllByScenario($scenario);
$outputUsersArray = Array();
foreach($events as $event)
{
$eventArray = Array();
$eventArray[JSONResponseFields::KEY_ID] = $event->getId();
$eventArray[JSONResponseFields::KEY_NAME] = $event->getOwner()->getId();
$outputEventsArray[] = $eventArray;
} ....
rise an error likes:
FatalErrorException: Error: Call to a member function getId() on a non-object in.....
You can use Doctrine Query builder to get this working. Assuming you have Querybuilder instance. The query would look like
$qb = this->getDoctrine()->getRepository('BundleName:Event')->createQueryBuilder('e');
$query = $qb
->select('e','p')
->innerjoin('u.owner','r')
->where('r.scenario= :scenario')
->setParameter('scenario', $scenarioid)
->getQuery();
$chatuser = $query->getResult();

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();

FosUserBundle and doctrine request

When I execute this query
public function SearchByfournisseur($keyWord)
{
$qb = $this->createQueryBuilder('p')->distinct()->select('p');
$qb ->leftJoin('p.Fournisseur', 'f');
$qb ->where($qb->expr()->eq('f.username', $keyWord));
$query = $qb->getQuery();
$products = $query->getResult();
return $products;
}
I got this error:
[Semantical Error] line 0, col 110 near 'test': Error: 'test' is not defined.
But this one works perfectly:
public function SearchByfournisseur($keyWord)
{
$qb = $this->createQueryBuilder('p')->distinct()->select('p');
$qb ->leftJoin('p.Fournisseur', 'f');
$qb ->where($qb->expr()->eq('f.id', $keyWord));
$query = $qb->getQuery();
$products = $query->getResult();
return $products;
}
That means that I can't access to the user's attributes except his id.
Is there any away to solve this problem?
EDIT:
This is the concerned entities :
<?php
namespace Ecommerce\boutiqueBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use FS\SolrBundle\Doctrine\Annotation as Solr;
/**
* Ecommerce\boutiqueBundle\Entity\Produit
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Ecommerce\boutiqueBundle\Entity\ProduitRepository")
*/
class Produit
{
/**
* #var integer $id
*#Solr\Id
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Ecommerce\UserBundle\Entity\User",inversedBy="Produits")
*
* #ORM\JoinColumn(name="Fournisseur_id", referencedColumnName="id")
*/
private $Fournisseur;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set Fournisseur
*
* #param string $Fournisseur
*/
public function setFournisseur( $Fournisseur)
{
$this->Fournisseur = $Fournisseur;
}
/**
* Get Fournisseur
*
* #return string
*/
public function getFournisseur()
{
return $this->Fournisseur;
}
}
Fournisseur entity:
<?php
namespace Ecommerce\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="Ecommerce_user")
*/
class User extends BaseUser
{
public function __construct()
{
parent::__construct();
$this->Produits = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Ecommerce\boutiqueBundle\Entity\Produit",
* mappedBy="Fournisseur")
*/
protected $Produits;
public function addProduit(\Ecommerce\boutiqueBundle\Entity\Produit $Produit)
{
$this->Produits[] = $Produit;
$Produit->setCategorie($this);
}
public function getProduits()
{
return $this->Produits;
}
}
You have to specify the join condition within the leftJoin() call.
public function SearchByfournisseur($keyWord)
{
$qb = $this->createQueryBuilder('p')->distinct()->select('p');
$qb ->leftJoin('p.Fournisseur', 'f', 'WITH', $qb->expr()->eq('f.username = ?', $keyWord));
$products = $query->getResult();
return $products;
}
I suggest you to read the Doctrine documentation chapter dealing about the QueryBuilder.

Resources