CDbCriteria mergeWith - bug

Check this:




$criteria = new CDbCriteria(array(

	'with'=>array(

		'user'=>array(

			'condition'=>'status=:status',

			'params'=>array(':status'=>2),

		),

	),

));


$criteria2 = new CDbCriteria(array(

	'with'=>array(

		'user'=>array(

			'condition'=>'id=:id',

			'params'=>array(':id'=>1),

		),

	),

));


$criteria->mergeWith($criteria2);


print_r($criteria->with);




output:


Array

(

    [user] => Array

        (

            [condition] => id=:id

            [params] => Array

                (

                    [:status] => 2

                    [:id] => 1

                )


        )


)



Question: where is the first part of condition?

i think, you must use addCondition() instead special condition

First of all - first criteria is defined in defaultScope, second - criteria in with() before findAll(), and defaultScope was overriden <_< addCondition() is not solution (I think)

with is not currently merged at all. We are thinking about changing this behavior. If there is not issue ticket on this yet, please create it.

samdark, Thanks!

Can you check and apply this patch?:




Index: CDbCriteria.php

===================================================================

--- CDbCriteria.php	(revision 1975)

+++ CDbCriteria.php	(working copy)

@@ -448,8 +448,26 @@

 

 		if(empty($this->with))

 			$this->with=$criteria->with;

-		else if(!empty($criteria->with))

-			$this->with=CMap::mergeArray($this->with, $criteria->with);

+		else if(!empty($criteria->with)){

+			$defaults=get_class_vars(__CLASS__);

+			unset($defaults['params']);

+

+			foreach($criteria->with as $k=>$v){

+				if(is_int($k))

+					$this->with[]=$v;

+				else if(is_array($v) && isset($this->with[$k])){

+					if(!(($with=$this->with[$k]) instanceof self))

+						$with=new self($this->with[$k]);

+					$with->mergeWith($v,$useAnd);

+					$this->with[$k]=array_diff_assoc($with->toArray(),$defaults);

+				}

+				else{

+					$this->with[$k]=$v;

+					if(false!==($offset=array_search($k,$this->with)))

+						unset($this->with[$offset]);

+				}

+			}

+		}

 	}

 

 	/**



UPD: duplicated relations (removed)

UPD: correct recursively $useAnd


$criteria = new CDbCriteria(array(

        'with'=>array(

                'user'=>array(

                        'condition'=>array('status=:status'),

                        'params'=>array(':status'=>2),

                ),

        ),

));


$criteria2 = new CDbCriteria(array(

        'with'=>array(

                'user'=>array(

                        'condition'=>array('id=:id'),

                        'params'=>array(':id'=>1),

                ),

        ),

));


$criteria->mergeWith($criteria2);


print_r($criteria->with);

try this~

sorry, but as I know, CDbCommandBuilder uses only string argument in ‘condition’ param (check code), that means you are wrong…