[Solucionado!] Criterios De Búsqueda Entre Varios Modelos

Tengo los siguientes modelos:

Proyectos, DirectoresProyectos, Docentes y Personas

Proyectos corresponde a la tabla proyectos (de mi base de datos)

DirectoresProyectos corresponde a la tabla directores_proyectos (de mi base de datos)

Docentes corresponde a la tabla docentes (de mi base de datos)

Personas corresponde a la tabla personas (de mi base de datos)

Los mismos están relacionados entre sí de la siguiente manera:




class Proyectos extends PActiveRecord

{

   public $nombre_director;


   public function relations()

   {

       return array(

          'directoresProyectos' => array(self::BELONGS_TO, 'DirectoresProyectos', 'directores_proyectos_id'),

       );

   }


}






class DirectoresProyectos extends PActiveRecord

{


   public function relations()

   {

       return array(

          'docentes' => array(self::BELONGS_TO, 'Docentes', 'docentes_id'),

          'proyectos' => array(self::HAS_MANY, 'Proyectos', 'directores_proyectos_id'),

       );

   }


}






class Docentes extends PActiveRecord

{


   public function relations()

   {

       return array(

          'directoresProyectoses' => array(self::HAS_MANY, 'DirectoresProyectos', 'docentes_id'),

          'personas' => array(self::BELONGS_TO, 'Personas', 'personas_id'),

       );

   }


}






class Personas extends PActiveRecord

{


   public function relations()

   {

       return array(

          'docentes' => array(self::HAS_MANY, 'Docentes', 'personas_id'),

       );

   }


}



O sea, los proyectos tienen un director, ese director es un docente y ese docente es una persona. No se si se entiende :unsure:

Las tablas tiene más campos pero solo les detallé los que permiten las relaciones.

El problema que tengo es que no se como hacer el "$criteria" dentro de "function search() del model Proyectos" para que en el "CGridView" de mi vista "admin" me permita buscar los directores por su nombre y apellido (sin un filter), o sea, que uno ingrese el nombre o apellido en el input de búsqueda de la vista admin y me filtre los proyectos por "nombres" o "apellidos" de los directores.

En el CGridView de la vista admin, muestro los nombres y apellidos de la siguiente manera (concatenados, ya que nombre y apellido son campos diferentes de mi tabla personas):




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

   'id'=>'proyectos-grid',

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

   'filter'=>$model,

   'columns'=>array(

        array(

            'name'=>'nombre_director',

            'value'=>'$data->directoresProyectos->docentes->personas->nombre." ".$data->directoresProyectos->docentes->personas->apellido',

            'htmlOptions'=>array('style'=>'width:150px;'),

            'headerHtmlOptions'=>array('style'=>'width:150px;text-align:center;'),

        ),

   ),

));



He probado poner así el criteria pero me sale el siguiente error:[color="#FF0000"] Trying to get property of non-object[/color]




public function search()

{

	$criteria=new CDbCriteria;

	$criteria->compare('nombre_director',$this->directoresProyectos->docentes->personas->nombre." ".$this->directoresProyectos->docentes->personas->apellido,true);


	return new CActiveDataProvider($this, array(

		'criteria'=>$criteria,

	));

}



si el criteria lo comento, la vista funciona perfectamente pero no anda el buscador de nombre y apellido :(

alguna idea??,

gracias por su ayuda!!! :D

:-[ alguna respuesta?? :(

Hola que tal,

Las relaciones solo las puedes usar cuando haces alguna búsqueda o el objeto tiene algún registro de BD, por ejemplo con un find(), findByAtributes(), etc. Cuando utilizas el search tu modelo no apunta a ningún registro de base de datos en particular o no viene de ninguna búsqueda, por lo que $this->directoresProyectos->docentes->personas->nombre no tiene sentido ya que tu modelo esta vació (solo se utiliza para realizar la búsqueda).

No muestras el código donde el usuario ingrese el nombre o apellido en el input de búsqueda de la vista admin, por lo que no te puedo dar una solución exacta, pero por lo general el criteria debería de quedar algo como:


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

Es decir para tu caso


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

igual el nombre del ATRIBUTO_DE_MODELO puede variar según como tengas el formulario.

Hola xavier!, gracias por contestar :) . Por fin una respuesta jejeje

Creo que no me expresé bien o tal vez interpretaste mal mi problema.

Yo tenía entendido que en la función search() del modelo se pueden definir los criterios de búsqueda de los campos del formulario que genera el zii.widgets.grid.CGridView (en este caso de mi vista admin.

El campo que quiero filtrar no pertenece al mismo modelo, sinó a una tabla que de alguna manera esta relacionada.

Proyectos (se relaciona con) DirectoresProyectos

DirectoresProyectos (se relaciona con) Docentes

Docentes (se relaciona con) Personas

Lo que quiero hacer es a través de una vista admin del modelo Proyectos (que genera el CRUD de gii), poder filtrar los proyectos por medio de los nombres de las personas (que están en el modelo Personas).

Los datos se muestran, pero no funciona el filtro, por eso mi duda esta en como definir el $criteria que esta en la función search() del modelo, o bien como hacer que funcione el filtro usando correctamente el Framework sin meter código CRUDO/NATIVO (que sería usarlo mal)

El código donde se pueden filtrar los datos es el que genera el CGridView:




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

   'id'=>'proyectos-grid',

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

   'filter'=>$model,

   'columns'=>array(

        array(

            'name' => 'nombre_director',

            'value'=> '$data->directoresProyectos->docentes->personas->nombre

                      ." "

                      .$data->directoresProyectos->docentes->personas->apellido',

            'htmlOptions'=>array('style'=>'width:150px;'),

            'headerHtmlOptions'=>array('style'=>'width:150px;text-align:center;'),

        ),

   ),

));



O sea, lo que hice fue definir un atributo en el modelo Proyectos, para poder utilizar ese nombre en el CGridView:




class Proyectos extends PActiveRecord

{

  public $nombre_director;




$nombre_director no existe en el modelo Proyectos como un campo de la tabla proyectos (sólo es el nombre que utilizo en ‘name’ => ‘nombre_director’, del CGridView )

‘directores_proyectos_id’ (es la FK desde Proyectos hacia DirectoresProyectos).

‘docentes_id’ (es la FK desde DirectoresProyectos hacia Docentes).

‘personas_id’ (es la FK desde Docentes hacia Personas).

las relaciones de las tablas son las que expliqué anteriormente en el otro post

la vista admin, funciona perfecto, mustra los nombres y apellidos, pero no anda el filtro de esa columna (ese sería el problema)

no se si se entiende…

o en Yii no se puede hacer lo que intento hacer? :huh:

SOLUCIONADO !!! :D :D :D

Bueno, paso a comentarles cómo solucioné mi problema:

Al atributo que declaré en el Modelo Proyectos




class Proyectos extends PActiveRecord

{

 

  public $nombre_director;

  ...

}



Tenía que incluirlo en la regla que determina que este campo es seguro en “search”, para que de esta forma se puedan realizar las comparaciones que se introducen en el buscador del grid




public function rules()

{

  return array(

    ...

    array('nombre_director', 'safe', 'on'=>'search'),

   );

}



Por último en la función search( ), agregué un criteria “with” con la relación:




$criteria->with = array('directoresProyectos.docentes.personas');

$criteria->compare('personas.nombre', $this->nombre_director, true );



Y la columna del Grid me quedó igual:




array(

   'name'=>'nombre_director',

   'value'=>'$data->directoresProyectos->docentes->personas->nombre',

   'htmlOptions'=>array('style'=>'width:150px;'),

   'headerHtmlOptions'=>array('style'=>'width:150px;text-align:center;'),

),



Sabía que venía por el lado de los $criteria :D :D :D

Hola hay alguna forma de filtrar en el CGridView solo los datos que sean de el usuario que este logued en ese momento?

por ejemplo, tengo estos modelos, Usuariosempresas y Vacantes, tengo las relaciones establecidas con HAS_MANY,

lo que quiero es que al momento de loguearme por ejemplo: "Me logueo"->usuario, al momento de ir a la vista admin de vacantes, me filtre los datos de las vacantes ya insertadas en un CGridView solo de ese usuario.

intente hacer esto:

En mi controlador de vacantes

public function actionListar()

{

$id_usuarioempresa= Yii:app()->user-id;//obtengo el id del usuario

‘:tipo’=$id_usuarioempresa;

$sql= 'select*from tbl_vacantes where ‘id_usuarioempresa =:tipo’;

$dataProvider = new (sqlDataProvider($sql)

$this->render(index,$dataProvider=>dataProvider)));

}

declaro el dataProvider en el CGridView de admin y nada.

soy nueva en yii y le eh buscado por todas partes y nada.

Si me podrían ayudar sería fantastico. Gracias

No te imaginas cuanto tiempo me gaste buscando una solucion tan simple, muchas gracias +1

Buenas seguì la guia pero me da el siguiente error:

include(micampo_search.php): failed to open stream: No such file or directory

Me dan una mano?

Gracias