Last active
April 18, 2018 22:01
-
-
Save leevigraham/11af9731e0cbeb5ce8c8e10c56766378 to your computer and use it in GitHub Desktop.
AbstractRepository::filterByCriteria - Parses a nested array and adds expressions to a query builder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Doctrine\ORM\Repository; | |
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; | |
use Doctrine\ORM\QueryBuilder; | |
abstract class AbstractRepository extends ServiceEntityRepository | |
{ | |
/** | |
* Parses a nested array and adds expressions to a query builder | |
* | |
* Example Array: | |
* | |
* Input: | |
* | |
* $criteria = [ | |
* 'condition' => 'andX', | |
* 'expressions' => [ | |
* [ | |
* 'propertyPath' => 'taskList.project.id', | |
* 'operator' => 'eq', | |
* 'value' => '1', | |
* ], | |
* [ | |
* 'propertyPath' => 'taskList.project.workspace.id', | |
* 'operator' => 'eq', | |
* 'value' => '1', | |
* ], | |
* ], | |
* ]; | |
* | |
* DQL: | |
* | |
* SELECT Task | |
* FROM App\Entity\Task Task | |
* INNER JOIN Task.taskList taskList | |
* INNER JOIN Task.project taskList_project | |
* INNER JOIN Task.workspace taskList_project_workspace | |
* WHERE taskList_project.id = 1 | |
* AND taskList_project_workspace.id = 1 | |
* | |
* @param QueryBuilder $qb | |
* @param array $criteria | |
* @param null $alias | |
*/ | |
public function filterByCriteria(QueryBuilder $qb, array $criteria, $alias = null) | |
{ | |
$alias = $alias ?: $qb->getRootAliases()[0]; | |
$expressionBuilder = $this->getEntityManager()->getExpressionBuilder(); | |
$expressions = []; | |
foreach ($criteria['expressions'] as $expression) { | |
if (key_exists('condition', $expression)) { | |
$expressions[] = $this->filterByCriteria($qb, $expression, $alias); | |
} else { | |
// Get the operator and value | |
switch ($expression['operator']) { | |
case 'eq': | |
case 'neq': | |
case 'lt': | |
case 'lte': | |
case 'gt': | |
case 'gte': | |
case 'between': | |
case 'isNull': | |
case 'isNotNull': | |
break; | |
case 'startsWith': | |
$expression['operator'] = 'LIKE'; | |
$expression['value'] = $expression['value'] . '%'; | |
break; | |
case 'endsWith': | |
$expression['operator'] = 'LIKE'; | |
$expression['value'] = '%' . $expression['value']; | |
break; | |
case 'contains': | |
$expression['operator'] = 'LIKE'; | |
$expression['value'] = '%' . $expression['value'] . '%'; | |
break; | |
} | |
// Explode the property path into it's parts | |
$propertyPathParts = explode('.', $expression['propertyPath']); | |
// Pop the property off the end | |
$property = array_pop($propertyPathParts); | |
/* | |
* Property is a dot delimited list. | |
* We need to make sure each alias is added | |
* These next few lines add the joins if required | |
* | |
* - task.taskList -> `$qb->join(task.taskList taskList)` | |
* - task.taskList.project -> `$qb->join(taskList.project taskList_project)` | |
* - task.taskList.project.workspace -> `$qb->oin(taskList_project.workspace taskList_project_workspace)` | |
*/ | |
$joinAlias = $alias; | |
foreach($propertyPathParts as $count => $propertyPart) { | |
$join = sprintf('%s.%s', $alias, $propertyPart); | |
$joinAlias = implode("_", array_slice($propertyPathParts, 0, $count+1)); | |
if(!in_array($joinAlias, $qb->getAllAliases())) { | |
$qb->join($join, $joinAlias); | |
} | |
} | |
// Now we have the final alias | |
// Join the alias and the property together | |
$expression['propertyPath'] = sprintf('%s.%s', $joinAlias, $property); | |
// Create the arguments | |
$expressionArguments = [$expression['propertyPath'], $expression['value']]; | |
// Create the expression | |
$expressions[] = call_user_func_array( | |
[$expressionBuilder, $expression['operator']], | |
$expressionArguments | |
); | |
} | |
} | |
// Apply all the expressions | |
$expression = call_user_func_array([ | |
$expressionBuilder, | |
$criteria['condition'], | |
], $expressions); | |
$qb->andWhere($expression); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment