Doctrine and join result type - symfony

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

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! :)

How convert my SQL statement to Doctrine QueryBuilder?

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?

Error in doctrine query : Binding an entity with a composite primary key to a query

Hello i have an entity with two primary keys .
class UsefulnessEvaluation
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="App\EvaluationBundle\Entity\Evaluation", cascade={"persist","remove"})
*/
private $evaluation;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="App\UserBundle\Entity\User", cascade={"persist","remove"})
*/
private $user;
/**
*
* #ORM\Column(type="string", nullable=false)
*/
private $type;
/**
* #ORM\Column(type="datetime", nullable=false)
*/
private $createdAt;
//etc
}
I want , in repository , count the number of an evaluation:
class UsefulnessEvaluationRepository extends EntityRepository
{
public function countEvaluationLikes($evaluation_id)
{
$query = $this->getEntityManager()->createQuery(
'SELECT count(p.evaluation) as nbre
FROM AppEvaluationBundle:UsefulnessEvaluation p
WHERE p.evaluation = :id
)->setParameter('id', $evaluation_id);
return $query->getSingleScalarResult();
}
}
this is the error :
Binding an entity with a composite primary key to a query is not
supported. You should split the parameter into the explicit fields and
bind them separately.
I think the issue is that you're selecting count(p.evaluation) but since you're already specifying the id of p.evaluation it seems unnecessary because you're guaranteed to get non-null values for p.evaluation.
Try this
$query = $this->getEntityManager()->createQuery(
'SELECT count(p) as nbre
FROM AppEvaluationBundle:UsefulnessEvaluation p
WHERE IDENTITY(p.evaluation) = :id'
)->setParameter('id', $evaluation_id);

Symfony2 setting other rows to 0 after/before flush

Here's what I'm having trouble with.
I've a Table which contains a column called shown_on_homepage and only one row should be set to 1, the rest should all be set to 0. I'm trying to add a new row to the database and this one should be set to 1, setting the one that previously had a 1 to 0.
In MySQL I know this can be achieved by issuing an update before the insert:
UPDATE table_name SET shown_on_homepage = 0
Here's my Entity:
class FeaturedPerson {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="content", type="string", length=2500, nullable=false)
*/
private $content;
/**
* #var \DateTime
*
* #ORM\Column(name="date_updated", type="datetime")
*/
private $dateUpdated;
/**
* #var bool
*
* #ORM\Column(name="shown_on_homepage", type="boolean", nullable=false)
*/
private $isShownOnHomepage;
//...
public function getIsShownOnHomepage() {
return $this->isShownOnHomepage;
}
public function setIsShownOnHomepage($isShownOnHomepage) {
$this->isShownOnHomepage = $isShownOnHomepage;
return $this;
}
}
And for the Controller I've:
$featured = new FeaturedPerson();
$featured->setContent('Test content.');
$featured->setDateUpdated('01/02/2013.');
$featured->setIsShownOnHomepage(TRUE);
$em = $this->getDoctrine()->getManager();
$em->persist($featured);
$em->flush();
It does add the new row, but the one that had a shown_on_homepage set to 1 still has it. I've researched but I couldn't find a way to achieve this, I hope you can help me.
You could execute a query prior to your existing code in your controller:
$queryBuilder = $this->getDoctrine()->getRepository('YourBundleName:FeaturedPerson')->createQueryBuilder('qb');
$result = $queryBuilder->update('YourBundleName:FeaturedPerson', 'd')
->set('d.isShownOnHomepage', $queryBuilder->expr()->literal(0))
->where('d.isShownOnHomepage = :shown')
->setParameter('shown', 1)
->getQuery()
->execute();
Change 'YourBundleName' to your bundle name.

Resources