Relations y clave compuesta

Hola gente,

tengo una dificultad a la hora de establecer el array de la función relations() entre un model simple con otro de clave compuesta.

La cosa es así: el model Agent tiene clave agentid y posee un campo country_id; dicho campo quiero relacionarlo al campo code de la tabla Dictionary que tiene clave compuesta ( type, code ), pues guarda todas las tablas del sistema.

He intentado un engendro como este en Agent::relations() sin éxito:


return array(

	'country' => array( self::HAS_ONE, 'Dictionary', 'code',

					'condition' => '`type` = :type',

					'params' => array( ':type' => "pais" ) 

				) );

La idea que busco es colocar en los views del admin y view que se muestre la descripción (Dictionary.text) del país en vez del código (Agent.country_id).

Gracias,

cbi

prueba




'country'=>array(self::BELONGS_TO,'Dictionary',

'',

'on'=>'country.type=\'pais\' and country.code=t.country_id','alias'=>'country'),



Hola Horacio,

Probé tu propuesta, pero tira CDbException:

Al realizar el traceo se ve que en la instrucción SQL falta la tabla Agent:


SELECT `country`.`type` AS `t1_c0`, `country`.`code`

AS `t1_c1`, `country`.`text` AS `t1_c2` FROM `Dictionary` `country` 

WHERE (country.type = 'country' And country.code = country_id)

¿Por qué puede ser que no esté colocando la relación con la tabla Agent?

Muchas gracias,

cbi

la relación esta bien, seguramente debas ver el código del accion del controlador

tienes la opción ?





$criteria->with= array('country');



postea el código de tu accion y de la vista

Horacio,

muchas gracias por tu tiempo. Acá van el contenido de los métodos en el controlador Agent:


	

public function actionView($id)

{

	$addressDataProvider = new CActiveDataProvider( 'AgentAddress', array(

															'criteria' => array(

																'condition' => 'agentid = :agentId',

																'params'=>array( ':agentId' => $id ),

															),

														'pagination'=> array(

															'pageSize' => 1,

														),

													));

	$contactDataProvider = new CActiveDataProvider( 'AgentContact', array(

															'criteria' => array(

																'condition' => 'agentid = :agentId',

																'params' => array( ':agentId' => $id ),

															),

														'pagination' => array(

															'pageSize' => 1,

														),

													));


	$this->render('view', array(

			'model'=> $this->loadModel( $id ),

			'addressDataProvider' => $addressDataProvider,

			'contactDataProvider' => $contactDataProvider,

		));

}



Nota mental: contactDataProvider y addressDataProvider están agregados pues cada Agente puede tener múltiples domicilios/contactos.




public function actionAdmin()

{

	$model=new Agent('search');

	$model->unsetAttributes();  // clear any default values


	if(isset($_GET['Agent']))

		$model->attributes=$_GET['Agent'];


	$this->render('admin',array(

			'model'=>$model,

		));

}



cbi

has puesto en el metodo "search" del modelo

y en loadModel del controlador




$criteria->with= array('country');



??

Horacio: acabo de hacerlo, pero sigue tirando el mismo tema… en la SQL no está Agent:

cbi

que raro, ese mismo error me daba a mi, pero lo solucione agregando el "with"

en que acción te da el error?

mi código es asi (uso la relacion dom_estado)







	public function relations()

	{

		return array(

                        'dom_estado'=>array(self::BELONGS_TO,'Dominios','','on'=>'dom_estado.dominio=\'DR_ESTADO_EGRESO\'and dom_estado.valor=t.estado','alias'=>'dom_estado'),

		);

	}





	public function search()

	{

		$criteria=new CDbCriteria;

                $criteria->with=array('dom_estado');


		$criteria->compare('dom_estado.descripcion',$this->estado,true);


		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

		));

	}








	public function loadModel()

	{

		if($this->_model===null)

		{

			if(isset($_GET['id']))

				$this->_model=Egreso::model()->with('dom_estado')->findbyPk($_GET['id']);

			if($this->_model===null)

				throw new CHttpException(404, Yii::t('app', 'The requested page does not exist.'));

		}

		return $this->_model;

	}




	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Egreso');

		$criteria=new CDbCriteria;

                $criteria->with=array('dom_estado');

                $dataProvider->setCriteria($criteria);


		$this->render('index',array(

			'dataProvider'=>$dataProvider,

		));

	}




admin.php





$this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'egreso-grid',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'columns'=>array(

            array(

                        'name'=>'estado',

                        'value'=>'($data->dom_estado)?$data->dom_estado->descripcion:""',

                    'sortable'=>'true',

                'header'=>'Estado',

                ),

....



_view.php





	<b><?php echo CHtml::encode($data->getAttributeLabel('estado')); ?>:</b>

	<?php echo CHtml::encode($data->dom_estado->descripcion); ?>

	<br />



Durante el "view", al querer ver un registro… sin embargo, al querer editarlo funciona correctamente e incluso muestra la dropbox con los paises.

Me llevo tu código y repasaré las líneas de libreo de Agile Web App, a ver en qué le estoy errando.

Muchas gracias por tu tiempo, y mañana postearé si encuentro la solución.

cbi

Ok. Informo los avances, aunque no funciona el método admin (ver más abajo):

  1. para generar la relación de la clase model en el método relations():

	return array(

		'dictionaryCountry' => array( self::BELONGS_TO, 'Dictionary', '',

							'on' => '`dictionaryCountry`.`type` = \'' . DICTIONARY_TYPE_COUNTRY . '\' And code = t.country_id' ),



  1. en los métodos action*() de la clase controller:



	public function actionIndex()

	{

		$dataProvider = new CActiveDataProvider('Agent');


		$criteria = new CDbCriteria;

		$criteria->with = array( 'dictionaryCountry' );

		$dataProvider->setCriteria( $criteria );


		// etc: invocación a $this->render(...)

	}



  1. en el loadModel() de la clase controller:

	public function loadModel($id)

	{

		$model = Agent::model()->with( 'dictionaryCountry' )->findByPk((int)$id);


		return $model;

	}



Y en el [font="Courier New"]::actionAdmin()[/font] ha surgido nuevamente el problema pues me arroja un:


CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.country_id' in 'where clause'

parecido a los casos anteriores al no colocar la tabla [font="Courier New"]Agent[/font] en el join; por las dudas el código en Agent::search() es:


	public function search()

	{

		$criteria = new CDbCriteria;

		$criteria->with = array('dictionaryCountry');

		$criteria->together = True;


		$criteria->compare('agent_id',$this->agent_id,true);

		$criteria->compare('type',$this->type);

		// $criteria->compare('country_id',$this->country_id,true);

		$criteria->compare('taxid',$this->taxid,true);

		$criteria->compare('name',$this->name,true);

		

		$criteria->compare( 'dictionaryCountry.code', $this->country_id, True );


		return new CActiveDataProvider( get_class($this), array(

			'criteria' => $criteria,			

		));

	}



Gracias de antemano,

cbi

El código que faltaba era en el views/Agent/admin.php, el campo value debe ser $data->varRel donde varRel es la clave de la relación:


	array(

           'name' => 'country_id',

           'filter' => CHtml::listData( Agent::getOptions( DICTIONARY_TYPE_COUNTRY ), 'code', 'text'),

           'value' => '$data->dictionaryCountry->text', 

           'sortable' => 'true',

           'header' => 'País',

	),

Espero sirva.

cbi