Hi everyone -
Over the last 3-4 years of working with Yii, on a number of occasions I’ve had situations where I wanted to use CdbCriteria to search for records in ways that were sometimes somewhat complicated. For example, I’ve had to catch 4 different cases in a table where -
CdbCriteria1 - OR - CdbCriteria2 - OR - CdbCriteria3 - OR - CdbCriteria4
Using mergeWith is an option if you’re working with up to 2 sets of criteria, but beyond that. doing additional merges -
$c1->mergeWith($c2,'OR');
and then
$c1->mergeWith($c3,'OR');
etc., nests the criteria so that they become
((($c1 OR $c2) OR $c3) OR $c4)
which is not what I wanted to achieve.
The solution I came up with, for better or worse, was this:
/**
* Accepts an array of active record criteria and merges them into one
*
* @param $criteriaArray
* @param string $condition
* @return CDbCriteria|null
*/
function implodeMergeCriteriaArray($criteriaArray,$condition='OR')
{
if(count($criteriaArray)>0)
{
$withArray = array();
$conditionArray = array();
$paramsArray = array();
$c = new CDbCriteria();
foreach($criteriaArray as $criteria)
{
// Merge the 'with' array
if(isset($criteria->with))
$withArray = array_merge_recursive($criteria->with, $withArray);
if(!empty($criteria->condition))
$conditionArray[] = $criteria->condition;
if(!empty($criteria->params))
$paramsArray += $criteria->params;
}
$condition = '( ' . implode(' ) ' . $condition . ' ( ',$conditionArray) . ' )';
$c->with = $withArray;
$c->condition = $condition;
$c->params = $paramsArray;
} else {
$c = null;
}
return $c;
}
I’m not saying it’s the best solution, but so far it’s worked for me and it might prove useful to someone else.