Reputation: 2148
I have following function:
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();
}
I want if variables such as $tags
, $categories
, $authors
or $source
provided by function caller this variables affect on the createQueryBuilder
, but if each of them does not provide by the function caller(variable with default value) they don't affect createQueryBuilder and make this condition neutral on query.
One way is I make the query with many if condition but it is very messy.
Is there any better solution?
Upvotes: 1
Views: 3048
Reputation: 484
The chalasr's response is good, but I suggest extract the logic of build conditions to a specific trait, so you avoid code duplication (DRY).
You can do something like:
<?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.
}
Then your class make use of the trait in this way:
<?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();
}
}
Upvotes: 1
Reputation: 13167
Something like this should do the trick:
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();
}
A bit ugly, but I don't see any better alternative.
Upvotes: 4