我试图根据列表位置找到每个类别中的商品总数
我要做的是,如果来自美国的用户访问该网站,则只显示该位置的记录。此外,侧栏上的类别小部件还应考虑该位置中每个类别下的列表总数。如果访问者点击芝加哥,则窗口小部件应重新计算以反映位置“芝加哥”
使用以下代码
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;
}
我可以检索所有类别,每个类别的总数不包含位置参数。
但是,如果我引入位置参数,则只检索那些在该位置有列表的类别。
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*/
}
列出实体
<?php
namespace Bundle\AdvertBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Bundle\FrameworkBundle\Entity\DocumentInterface;
use Bundle\FrameworkBundle\Entity\BaseEntity;
/**
* @ORM\Entity (repositoryClass="Bundle\AdvertBundle\Repository\ListingItemRepository")
* @ORM\Table(name="listings")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="listing_type", type="string")
* @ORM\DiscriminatorMap({
"forsale" = "ForsaleItem",
"service" = "ServiceItem",
"job" = "JobItem",
"realestate" = "RealEstateItem",
"land" = "LandItem",
"house" = "HouseItem"
})
*/
abstract class ListingItem extends BaseEntity
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $title;
/**
* @var string
*
* @ORM\Column(name="slug", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $slug;
/**
* @var string
*
* @ORM\Column(name="price", type="decimal", precision=0, scale=2, nullable=false, unique=false)
*/
protected $price;
/**
* @var string
*
* @ORM\Column(name="description", type="text", precision=0, scale=0, nullable=false, unique=false)
*/
protected $description;
/**
* @var string
*
* @ORM\Column(name="thumbnail", type="string", length=255, precision=0, scale=0, nullable=true, unique=false)
*/
protected $thumbnail;
/**
* @var string
*
* @ORM\Column(name="status", type="string", length=100, precision=0, scale=0, nullable=false, unique=false)
*/
protected $status;
/**
* @var \DateTime
*
* @ORM\Column(name="date_created", type="datetime", precision=0, scale=0, nullable=true, unique=false)
*/
protected $dateCreated;
/**
* @var \DateTime
*
* @ORM\Column(name="date_approved", type="datetime", precision=0, scale=0, nullable=true, unique=false)
*/
protected $dateApproved;
/**
* @var \Bundle\AdvertBundle\Entity\Category
*
* @ORM\ManyToOne(targetEntity="Bundle\AdvertBundle\Entity\Category", inversedBy="listings")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=true)
* })
*/
protected $category;
/**
* @var \Bundle\UserBundle\Entity\User
*
* @ORM\ManyToOne(targetEntity="Bundle\UserBundle\Entity\User", inversedBy="listings")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
* })
*/
protected $user;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $name;
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $email;
/**
* @var string
*
* @ORM\Column(name="contact_number", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $contactNumber;
/**
* @var \Bundle\LocationBundle\Entity\Country
*
* @ORM\ManyToOne(targetEntity="Bundle\LocationBundle\Entity\Country")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="country_id", referencedColumnName="id", nullable=true)
* })
*/
private $country;
/**
* @var \Bundle\LocationBundle\Entity\State
*
* @ORM\ManyToOne(targetEntity="Bundle\LocationBundle\Entity\State")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="state_id", referencedColumnName="id", nullable=true)
* })
*/
private $state;
/**
* @var \Bundle\LocationBundle\Entity\City
*
* @ORM\ManyToOne(targetEntity="Bundle\LocationBundle\Entity\City")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="city_id", referencedColumnName="id", nullable=true)
* })
*/
private $city;
protected $dateformat = 'd-M-Y';
}
位置实体
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity (repositoryClass="Bundle\LocationBundle\Repository\LocationRepository")
* @ORM\Table(name="locations")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="location_type", type="string")
* @ORM\DiscriminatorMap({
"country" = "Country",
"state" = "State",
"city" = "City"
})
*/
abstract class Location
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $name;
/**
* @var string
*
* @ORM\Column(name="country_code", type="string", length=3, precision=0, scale=0, nullable=true, unique=false)
*/
protected $countryCode;
/**
* @var string
*
* @ORM\Column(name="slug", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $slug;
/**
* @var integer
*
* @ORM\Column(name="geoname_id", type="integer", precision=0, scale=0, nullable=false, unique=false)
*/
protected $geonameId;
/**
* @var string
*
* @ORM\Column(name="lng", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $lng;
/**
* @var string
*
* @ORM\Column(name="lat", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
protected $lat;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Bundle\LocationBundle\Entity\Location", mappedBy="parent")
*/
protected $children;
/**
* @var \Bundle\LocationBundle\Entity\Location
*
* @ORM\ManyToOne(targetEntity="Bundle\LocationBundle\Entity\Location", inversedBy="children")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
* })
*/
protected $parent;
/**
* @var string
*
* @ORM\Column(name="currency_symbol", type="string", length=100, precision=0, scale=0, nullable=true, unique=false)
*/
protected $currencySymbol;
/* 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 :(得分:0)
使用您的WHERE,您将过滤掉所有不匹配类别的内容,因此无法计算它们。应该可以通过一个查询来执行,但是您必须从WHERE移动条件以获得甚至不匹配的行并将它们计为0。 Simple SQL version:
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
在Doctrine中没有IF,但你可以使用
CASE WHEN (<cond>) THEN 1 ELSE 0
使用$ orx expr。
另一个可能性是将条件移动到this example之类的连接,但是你必须在学说中指定自定义ON:
来自文档的:任意JOIN语法(FROM User u JOIN Comment c WITH c.user = u.id) 那么你将为这三个联合表总计三个计数。这是可行但丑陋的。
或@ denys281所述的子查询 - 仅从类别中选择,但select子句包含列,该列计算每个类别的所有匹配列表。
答案 1 :(得分:0)
经过几天查阅学说中的子查询后,我终于得到了适合我情况的代码。 以下是一些让我重新思考如何编写第一个代码的pionts。
显而易见的解决方案是使用@ danys281建议的子查询。
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();
}
谢谢大家给我的提示。