Symfony 原则2:在单表继承中,在一对多关联中获取所有具有或不具有匹配记录的记录
我试图找到总计数的清单在每个类别的基础上上市的位置 我想做的是,如果一个来自美国的用户访问该站点,只会显示该位置的记录。侧边栏上的category小部件还应考虑该位置每个类别下的列表总数。如果访问者点击芝加哥,小部件应该重新计算以反映“芝加哥”的位置 使用下面的代码Symfony 原则2:在单表继承中,在一对多关联中获取所有具有或不具有匹配记录的记录,symfony,orm,doctrine-orm,Symfony,Orm,Doctrine Orm,我试图找到总计数的清单在每个类别的基础上上市的位置 我想做的是,如果一个来自美国的用户访问该站点,只会显示该位置的记录。侧边栏上的category小部件还应考虑该位置每个类别下的列表总数。如果访问者点击芝加哥,小部件应该重新计算以反映“芝加哥”的位置 使用下面的代码 public function findCategoriesWithTotalListing($location) { $builder = $this->_em->createQueryBuilder(
public function findCategoriesWithTotalListing($location)
{
$builder = $this->_em->createQueryBuilder();
$builder->select('c, count(l.id) AS num')
->from('Bundle\AdvertBundle\Entity\Category', 'c')
->leftJoin('c.listings','l')
->leftJoin('l.country','co')
->leftJoin('l.state','st')
->leftJoin('l.city','ci');
$builder->groupBy('c.id');
$result = $builder->getQuery()->getArrayResult();
print_r($result);
exit;
}
我能够检索所有类别,每个列表的总计数不带location参数
但是,如果我引入location参数,则仅检索在该位置具有列表的类别
public function findCategoriesWithTotalListing($location)
{
$builder = $this->_em->createQueryBuilder();
$builder->select('c, count(l.id) AS num')
->from('Bundle\AdvertBundle\Entity\Category', 'c')
->leftJoin('c.listings','l')
->leftJoin('l.country','co')
->leftJoin('l.state','st')
->leftJoin('l.city','ci');
$orx = $builder->expr()->orX();
$orx->add($builder->expr()->like("co.slug", ':location'));
$orx->add($builder->expr()->like("st.slug", ':location'));
$orx->add($builder->expr()->like("ci.slug", ':location'));
$builder->andWhere($orx);
$builder->groupBy('c.id');
$builder->setParameter('location',$location);
$result = $builder->getQuery()->getArrayResult();
print_r($result);
exit;
}
我要所有类别
我可能做错了什么
谢谢
以下实体
类别实体
<?php
namespace Bundle\AdvertBundle\Entity;
use Bundle\FrameworkBundle\Entity\BaseEntity;
use Bundle\FrameworkBundle\Entity\DocumentInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Category
*
* @ORM\Table(name="listings_categories")
* @ORM\Entity(repositoryClass="Bundle\AdvertBundle\Repository\CategoryRepository")
*/
class Category extends BaseEntity implements DocumentInterface
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="slug", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
private $slug;
/**
* @var string
*
* @ORM\Column(name="summary", type="text", precision=0, scale=0, nullable=false, unique=false)
*/
private $summary;
/**
* @var integer
*
* @ORM\Column(name="parent", type="integer", precision=0, scale=0, nullable=false, unique=false)
*/
private $parent;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="ListingItem", mappedBy="category")
*/
private $listings;
/**
* @var string
*
* @ORM\Column(name="thumbnail", type="string", length=255, precision=0, scale=0, nullable=true, unique=false)
*/
private $thumbnail;
/**
* @var string
*
* @ORM\Column(name="form_template", type="string", length=255, precision=0, scale=0, nullable=true, unique=false)
*/
private $formTemplate;
private $children;
private $totalChildren;
private $totaListing;
/* Getters and Setters*/
}
国家实体
namespace Bundle\LocationBundle\Entity;
use Bundle\FrameworkBundle\Entity\DocumentInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Country
*
* @ORM\Table(name="locations")
* @ORM\Entity(repositoryClass="Bundle\LocationBundle\Repository\LocationRepository")
*/
class Country extends Location
{
/**
* Set countryCode
*
* @param string $countryCode
* @return Country
*/
public function setCountryCode($countryCode)
{
$this->countryCode = $countryCode;
return $this;
}
/**
* Get countryCode
*
* @return string
*/
public function getCountryCode()
{
return $this->countryCode;
}
}
州和城市实体就像国家一样,你在那里过滤掉所有不匹配的类别,因此它无法计算它们。应该可以通过一个查询完成,但您必须将条件从何处移动,以获取甚至不匹配的行,并将它们计为0。 在教义中没有IF,但你可以使用
CASE WHEN (<cond>) THEN 1 ELSE 0
CASE WHEN()然后是1,否则为0
当您使用$orx expr时
另一个可能性是将条件移动到那些连接中,如中所示,但随后您必须执行任意连接原则,以指定自定义:
来自文档:任意连接语法(来自用户u JOIN注释c,其中c.User=u.id)
然后,将这三个联接表的三个计数相加。这是可行的,但很难看
或者@denys281所述的子查询-仅从类别中选择,但select子句包含统计每个类别的所有匹配列表的列。在原则中研究子查询几天后,我终于得到了适用于我的情况的代码。 下面是一些让我重新思考如何编写第一个代码的例子
public function findCategoriesWithTotalListing($location)
{
$subQuery = $this->_em->createQueryBuilder();
$subQuery->select('COUNT(l.id)')
->from('Bundle\AdvertBundle\Entity\ListingItem','l')
->leftJoin('l.category','cat')
->leftJoin('l.country','co')
->leftJoin('l.state','st')
->leftJoin('l.city','ci')
->where('cat.id = c.id');
if($location instanceOf Country){
$subQuery->andWhere('co.slug = :location');
}
if($location instanceOf State){
$subQuery->andWhere('st.slug = :location');
}
if($location instanceOf City){
$subQuery->andWhere('ci.slug = :location');
}
$subQuery->andWhere("l.status = :status");
$builder = $this->_em->createQueryBuilder();
$builder->select("c, (".$subQuery->getDql().") AS num")
->from('Bundle\AdvertBundle\Entity\Category', 'c')
->setParameters(['location'=>$location->getSlug(),'status'=>'active'])
->groupBy('c');
return $builder->getQuery()->getResult();
}
谢谢大家给我的提示。如果您想在一个查询中统计每个类别中的项目,我认为您必须使用子查询。现在,您可以计算所有类别中具有相同位置的项目。或者你可以只做3个单独的查询,计算每个类别中的项目。是的,我想从访客当前位置计算每个类别下的所有项目,所以我认为你需要子查询,或者3个单独的查询。
SELECT c.*, sum(IF(loc.code = 'x', 1, 0))
FROM category c
LEFT JOIN list l ON c.id = l.c_id
LEFT JOIN loc ON loc.id = l.loc_id
GROUP BY c.id
CASE WHEN (<cond>) THEN 1 ELSE 0
public function findCategoriesWithTotalListing($location)
{
$subQuery = $this->_em->createQueryBuilder();
$subQuery->select('COUNT(l.id)')
->from('Bundle\AdvertBundle\Entity\ListingItem','l')
->leftJoin('l.category','cat')
->leftJoin('l.country','co')
->leftJoin('l.state','st')
->leftJoin('l.city','ci')
->where('cat.id = c.id');
if($location instanceOf Country){
$subQuery->andWhere('co.slug = :location');
}
if($location instanceOf State){
$subQuery->andWhere('st.slug = :location');
}
if($location instanceOf City){
$subQuery->andWhere('ci.slug = :location');
}
$subQuery->andWhere("l.status = :status");
$builder = $this->_em->createQueryBuilder();
$builder->select("c, (".$subQuery->getDql().") AS num")
->from('Bundle\AdvertBundle\Entity\Category', 'c')
->setParameters(['location'=>$location->getSlug(),'status'=>'active'])
->groupBy('c');
return $builder->getQuery()->getResult();
}