如果提供条件,学说将条件添加到 createQueryBuilder
Doctrine add condition to createQueryBuilder if condition provided
我有以下功能:
public function latestNews($tags = array(), $categories = array(), $authors = array(), $lang = 'en', $source = '', $limit = 20) {
return $this->createQueryBuilder('News')
->field('tags')->in($tags)
->field('categories')->in($category)
->field('authors')->in($authors)
->field('lang')->equals($lang)
->sort('date' -> 'DESC')
->field('source')->equals($source)
->limit($limit)
->getQuery()
->execute();
}
我想如果函数调用者提供的 $tags
、$categories
、$authors
或 $source
等变量会影响 createQueryBuilder
,但是如果它们中的每一个都不由函数调用者提供(具有默认值的变量),则它们不会影响 createQueryBuilder 并使此条件在查询时保持中立。
一种方法是我用很多 if 条件进行查询,但它非常混乱。
有没有更好的解决办法?
像这样应该可以解决问题:
public function latestNews($tags = array(), $categories = array(), authors = array(), $lang = 'en', $source = '', $limit = 20) {
$inClauses = ['tags', 'categories', 'authors'];
$equalClauses = ['lang', 'source'];
$qb = $this->createQueryBuilder('News');
foreach ($inClauses as $field) {
$realVar = ${$field};
if (!empty($realVar)) {
$qb->field($field)->in($realVar);
}
}
foreach ($equalClauses as $field) {
$realVar = ${$field};
if ($realVar) {
$qb->field($field)->equals($realVar);
}
}
return $qb
->sort('date' -> 'DESC')
->limit($limit)
->getQuery()
->execute();
}
有点难看,但我看不出有更好的选择。
chalasr 的反应很好,但我建议将构建条件的逻辑提取到特定特征,这样可以避免代码重复(DRY)。
您可以这样做:
<?php
namespace Xthiago\My\Path;
use \Doctrine\DBAL\Query\QueryBuilder;
trait DoctrineQueryHelper
{
public function in(QueryBuilder $qb, array $filter, $field)
{
if (empty($filter[$field])) {
return $this;
}
$qb->field($field)->in($filter[$field]);
return $this;
}
public function equals(QueryBuilder $qb, array $filter, $field)
{
if (empty($filter[$field])) {
return $this;
}
$qb->field($field)->equals($filter[$field]);
return $this;
}
public function lang(QueryBuilder $qb, $value = 'en')
{
$qb->field('lang')->equals($value);
return $this;
}
public function limit(QueryBuilder $qb, $value = 20)
{
$qb->limit($value);
return $this;
}
// you can create a lot of helper methods here in order to avoid duplicity.
}
然后你的class以这种方式利用特征:
<?php
namespace Xthiago\My\Path;
use \Doctrine\DBAL\Query\QueryBuilder;
class NewsRepository
{
use DoctrineQueryHelper;
/**
* @param array $filter as follow:
* <code>
* [
* 'tags' => [],
* 'categories' => [],
* 'authors' => [],
* 'lang' => 'en',
* 'source' => '',
* 'limit' => 20,
* ]
* </code>
*
* @return array with results.
*/
public function latestNews(array $filter = [])
{
$qb = $this->createQueryBuilder('News');
$this->in($qb, $filter, 'tags')
->in($qb, $filter, 'categories')
->in($qb, $filter, 'authors')
->equals($qb, $filter, 'source')
->lang($qb, $filter)
->limit($qb, $filter);
return $qb->sort('date', 'DESC')
->getQuery()
->execute();
}
}
我有以下功能:
public function latestNews($tags = array(), $categories = array(), $authors = array(), $lang = 'en', $source = '', $limit = 20) {
return $this->createQueryBuilder('News')
->field('tags')->in($tags)
->field('categories')->in($category)
->field('authors')->in($authors)
->field('lang')->equals($lang)
->sort('date' -> 'DESC')
->field('source')->equals($source)
->limit($limit)
->getQuery()
->execute();
}
我想如果函数调用者提供的 $tags
、$categories
、$authors
或 $source
等变量会影响 createQueryBuilder
,但是如果它们中的每一个都不由函数调用者提供(具有默认值的变量),则它们不会影响 createQueryBuilder 并使此条件在查询时保持中立。
一种方法是我用很多 if 条件进行查询,但它非常混乱。
有没有更好的解决办法?
像这样应该可以解决问题:
public function latestNews($tags = array(), $categories = array(), authors = array(), $lang = 'en', $source = '', $limit = 20) {
$inClauses = ['tags', 'categories', 'authors'];
$equalClauses = ['lang', 'source'];
$qb = $this->createQueryBuilder('News');
foreach ($inClauses as $field) {
$realVar = ${$field};
if (!empty($realVar)) {
$qb->field($field)->in($realVar);
}
}
foreach ($equalClauses as $field) {
$realVar = ${$field};
if ($realVar) {
$qb->field($field)->equals($realVar);
}
}
return $qb
->sort('date' -> 'DESC')
->limit($limit)
->getQuery()
->execute();
}
有点难看,但我看不出有更好的选择。
chalasr 的反应很好,但我建议将构建条件的逻辑提取到特定特征,这样可以避免代码重复(DRY)。
您可以这样做:
<?php
namespace Xthiago\My\Path;
use \Doctrine\DBAL\Query\QueryBuilder;
trait DoctrineQueryHelper
{
public function in(QueryBuilder $qb, array $filter, $field)
{
if (empty($filter[$field])) {
return $this;
}
$qb->field($field)->in($filter[$field]);
return $this;
}
public function equals(QueryBuilder $qb, array $filter, $field)
{
if (empty($filter[$field])) {
return $this;
}
$qb->field($field)->equals($filter[$field]);
return $this;
}
public function lang(QueryBuilder $qb, $value = 'en')
{
$qb->field('lang')->equals($value);
return $this;
}
public function limit(QueryBuilder $qb, $value = 20)
{
$qb->limit($value);
return $this;
}
// you can create a lot of helper methods here in order to avoid duplicity.
}
然后你的class以这种方式利用特征:
<?php
namespace Xthiago\My\Path;
use \Doctrine\DBAL\Query\QueryBuilder;
class NewsRepository
{
use DoctrineQueryHelper;
/**
* @param array $filter as follow:
* <code>
* [
* 'tags' => [],
* 'categories' => [],
* 'authors' => [],
* 'lang' => 'en',
* 'source' => '',
* 'limit' => 20,
* ]
* </code>
*
* @return array with results.
*/
public function latestNews(array $filter = [])
{
$qb = $this->createQueryBuilder('News');
$this->in($qb, $filter, 'tags')
->in($qb, $filter, 'categories')
->in($qb, $filter, 'authors')
->equals($qb, $filter, 'source')
->lang($qb, $filter)
->limit($qb, $filter);
return $qb->sort('date', 'DESC')
->getQuery()
->execute();
}
}