Chaining CdbCriteria

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.