在 ManyToMany Doctrine queryBuilder() 中 ForeignKey 为 NULL 的实体上 select 时查询异常
Query Exception when select on entity where ForeignKey is NULL in a ManyToMany Doctrine queryBuilder()
在我的 Symfony 项目中,我有两个实体 Product.php
和 Configuration.php
。
这是一个ManyToMany
关系。
这是 Product.php
中的关系:
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Configuration", inversedBy="products")
* @ORM\JoinTable(name="product_configuration",
* joinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="product_id", nullable=true)},
* inverseJoinColumns={@ORM\JoinColumn(name="configuration_id", referencedColumnName="configuration_id")}
* )
**/
protected $configurations;
这是Configuration.php
:
/**
* Describes the products using $this configuration
*
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Product", mappedBy="configurations")
**/
protected $products;
在一个页面中,我需要恢复产品,其中没有一些配置 , 例如 FK 配置 是 NULL.
所以我在 Productrepository.php
中创建了这个 queryBuilder()/dql :
public function getProductForCurrentWorkType($slug)
{
// First we get all the product even with configurations
$selectProduct = $this->getEntityManager()->createQueryBuilder();
$selectProduct
->select('p, wt, c')
->from('MyBundle:Product', 'p')
->join('p.workType', 'wt', 'WITH', 'wt.id = p.workType')
->join('p.configurations', 'c')
->where('wt.slug = :slug')
->setParameters(array('slug' => $slug));
// Then we apply a filter where configurations is null for product.
// We get all products where product.id are not in ids of the first request
$nullConfiguration = $this->getEntityManager()->createQueryBuilder();
$nullConfiguration
->select('pr.id')
->from('MyBundle:Product', 'pr')
->where($nullConfiguration->expr()->notIn('pr.id', $selectProduct->getDQL()));
return $nullConfiguration->getQuery()->getResult();
}
如果我 return 仅第一个查询 e-g $selectProduct
,则第一个步骤效果很好。它 return 仅适用于具有 $slug
配置的产品。
但是如果我return第二个查询(下面的代码),就会出现错误:
2/2 [Syntax Error] line 0, col 69: Error: Expected
Doctrine\ORM\Query\Lexer::T_FROM, got ','
1/2 QueryException: SELECT pr FROM MyBundle:Product pr WHERE pr.id NOT
IN(SELECT p, wt, c FROM MyBundle:Product p INNER JOIN p.workType
wt WITH wt.id = p.workType INNER JOIN p.configurations c WHERE wt.slug
= :slug)
我该如何解决这个错误?
编辑
我在 ProductRepository.php
中尝试的另一种解决方案:
$selectProduct = $this->getEntityManager()->createQueryBuilder();
$selectProduct
->select('p, wt, c')
->from('MyBundle:Product', 'p')
->join('p.workType', 'wt', 'WITH', 'wt.id = p.workType')
->join('p.configurations', 'c')
->having('COUNT(c.id) = 0') // check if the collection is empty
->where('wt.slug = :slug')
->setParameters(array('slug' => $slug));
return $selectProduct
->getQuery()
->getResult();
现在我的控制器,如果它可以帮助你:
$em = $this->getDoctrine()->getManager();
$arrayProduct = $this->getDoctrine()->getRepository('MyBundle:Product')->getProductForCurrentWorkType($slug);
if (!$arrayProduct) {
throw $this->createNotFoundException('Unable to find a Product !');
}
//return statement
下面的代码 return 告诉我 找不到产品!,如果我用抛出 $this->createNotFoundException
删除 if 条件,页面是显示正确但没有结果。
试试这个:
$qb->select('p')
->from('Product','p')
->leftJoin('p.configurations','c')
->having('COUNT(c.id) = 0') // check if the collection is empty
->groupBy('p.id');
在我的 Symfony 项目中,我有两个实体 Product.php
和 Configuration.php
。
这是一个ManyToMany
关系。
这是 Product.php
中的关系:
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Configuration", inversedBy="products")
* @ORM\JoinTable(name="product_configuration",
* joinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="product_id", nullable=true)},
* inverseJoinColumns={@ORM\JoinColumn(name="configuration_id", referencedColumnName="configuration_id")}
* )
**/
protected $configurations;
这是Configuration.php
:
/**
* Describes the products using $this configuration
*
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Product", mappedBy="configurations")
**/
protected $products;
在一个页面中,我需要恢复产品,其中没有一些配置 , 例如 FK 配置 是 NULL.
所以我在 Productrepository.php
中创建了这个 queryBuilder()/dql :
public function getProductForCurrentWorkType($slug)
{
// First we get all the product even with configurations
$selectProduct = $this->getEntityManager()->createQueryBuilder();
$selectProduct
->select('p, wt, c')
->from('MyBundle:Product', 'p')
->join('p.workType', 'wt', 'WITH', 'wt.id = p.workType')
->join('p.configurations', 'c')
->where('wt.slug = :slug')
->setParameters(array('slug' => $slug));
// Then we apply a filter where configurations is null for product.
// We get all products where product.id are not in ids of the first request
$nullConfiguration = $this->getEntityManager()->createQueryBuilder();
$nullConfiguration
->select('pr.id')
->from('MyBundle:Product', 'pr')
->where($nullConfiguration->expr()->notIn('pr.id', $selectProduct->getDQL()));
return $nullConfiguration->getQuery()->getResult();
}
如果我 return 仅第一个查询 e-g $selectProduct
,则第一个步骤效果很好。它 return 仅适用于具有 $slug
配置的产品。
但是如果我return第二个查询(下面的代码),就会出现错误:
2/2 [Syntax Error] line 0, col 69: Error: Expected Doctrine\ORM\Query\Lexer::T_FROM, got ','
1/2 QueryException: SELECT pr FROM MyBundle:Product pr WHERE pr.id NOT IN(SELECT p, wt, c FROM MyBundle:Product p INNER JOIN p.workType wt WITH wt.id = p.workType INNER JOIN p.configurations c WHERE wt.slug = :slug)
我该如何解决这个错误?
编辑
我在 ProductRepository.php
中尝试的另一种解决方案:
$selectProduct = $this->getEntityManager()->createQueryBuilder();
$selectProduct
->select('p, wt, c')
->from('MyBundle:Product', 'p')
->join('p.workType', 'wt', 'WITH', 'wt.id = p.workType')
->join('p.configurations', 'c')
->having('COUNT(c.id) = 0') // check if the collection is empty
->where('wt.slug = :slug')
->setParameters(array('slug' => $slug));
return $selectProduct
->getQuery()
->getResult();
现在我的控制器,如果它可以帮助你:
$em = $this->getDoctrine()->getManager();
$arrayProduct = $this->getDoctrine()->getRepository('MyBundle:Product')->getProductForCurrentWorkType($slug);
if (!$arrayProduct) {
throw $this->createNotFoundException('Unable to find a Product !');
}
//return statement
下面的代码 return 告诉我 找不到产品!,如果我用抛出 $this->createNotFoundException
删除 if 条件,页面是显示正确但没有结果。
试试这个:
$qb->select('p')
->from('Product','p')
->leftJoin('p.configurations','c')
->having('COUNT(c.id) = 0') // check if the collection is empty
->groupBy('p.id');