Relacion Entre Vistas

Buenas tardes, primero que nada gracias por cualquier ayuda que me puedan dar. tengo unas pocas semanas usando Yii y la verdad me ha costado un poco. aqui la pregunta.

Estoy tratando de hacer un sistema que tiene varios niveles de busqueda. por ejemplo:

Entro a Organismo y me salen todos los organismos (Vista admin.php de organismos), despues de filtrar los organimos y encontrar el que deseo, puedo entrar al organismo seleccionado (View.php del organismo), lo que quiero ahora es hacer que desde esta vista se direccione hacia otra vista donde se listen (sub-organismos/admin.php) los suborganismos relacionados con este organismo. no se si me explique.

las tablas se relacionan asi.

Organimso

id

nombre

suborganismo

id

idorganismo

nombre

en el view.php de los organismos tengo este arreglo en el menu que redirecciona hacia los suborganismos, lo que quisiera es poder pasarle el id del organismos para despues de alguna manera mostrar solo los que vienen relacionado con el organismo en el que me encontraba.


$this->menu=array(

	array('label'=>'Listado de Organismos', 'url'=>array('index')),

	array('label'=>'Nuevo Organismo', 'url'=>array('create')),

	array('label'=>'Actualizar Organismo', 'url'=>array('update', 'id'=>$model->id)),

	array('label'=>'Eliminar Organismo', 'url'=>'#', 'linkOptions'=>array('submit'=>array('delete','id'=>$model->id),'confirm'=>'Are you sure you want to delete this item?')),

	array('label'=>'Administrar Organismos', 'url'=>array('admin')),

	array('label'=>'Sub Organismos', 'url'=>array('SubOrganismos/admin')),

);

?>

si no me supe explicar haganmelo saber.

Lo que necesito es traerme el id de el organismo para poder mostrar los suborganismos que estan relacionados solamente con ese organismo… alguna idea? :(

Aunque aún soy un novato en Yii, entiendo lo que quieres hacer y en realidad es complicado tratar estructuras así. Yo tengo algo similar y lo hice así, pasándole el ID por GET:


array('label'=>'Sub Organismos', 'url'=>array('SubOrganismos/admin/'.$model->id))

Asumiendo que SubOrganismos es otro controller y admin un action del mismo, en el action admin tomas el id y traes todos los suborganismos:


public function admin($id){

	$subOrganismos = SubOrganismos::model()->findAll('id_organismo='.$id);

Ojalá te sirva, no aseguro que sea la mejor forma de hacerlo, es por eso que si alguien conoce otro método para hacerlo, bienvenida sea la corrección o sugerencia.

Saludos.

hola cristobal gracias por la ayuda, yo habia pensado usar el get. ahora lo que no me queda claro es lo de la function admin, disculpa pero tengo muy poco tiempo usando esto y ando muuuy enredado. donde esta esa funcion? en el “views/suborganismos/admin”???

otra cosa, entiendo que lo pueda pasar a traves del get y almacenar dentro de una variable. pero, como podria actualizar los filtros para que vinieran precargados con esa busqueda?

Entiendo que tienes la siguiente estructura:

controllers/

[indent]OrganismosController.php

SubOrganismosController.php[/indent]

models/

[indent]Organismos.php

SubOrganismos.php[/indent]

views/

[indent]organismos/

[indent]admin.php

view.php[/indent]

[/indent]

[indent]suborganismos/

[indent]admin.php

view.php[/indent]

[/indent]

Entonces, dentro de views/organismos/view.php tienes la línea

array(‘label’=>‘Sub Organismos’, ‘url’=>array(’[color="#FF0000"]suborganismos[/color]/[color="#0000FF"]admin[/color]/’.$model->id))

Donde [color="#FF0000"]suborganismos [/color] (ojo con el uso de mayúsculas) corresponde al controllador SubOrganismosController.php y [color="#0000FF"]admin [/color]al action (función o método) admin que está dentro de dicho controlador.

¿Es así o lo tienes de otra forma?

Lo que yo hago es lo siguiente

VISTA

Código para cambiar la URL cuando se selecciona un organismo (vista admin de organismos)

Yii::app()->getClientScript()->registerScript ( 'ChangeSelectedRowEvent', 'function ChangeHrefs(idRow) {

		id=$("#"+idRow).yiiGridView("getSelection")||0;	

		if(id!=0){

			var urlSuborganismos="'.Yii::app()->createUrl('suborganismos/index',array('id'=>'_id_')).'";

			urlSuborganismos=urlSuborganismos.replace("_id_",id);

			$("#lnkSuborganismos").attr("href",urlSuborganimos);			

		}else{

			$("#lnkSuborganismos").removeAttr("href");			

		}

	}

	', CClientScript::POS_END );

Código del CGridView, se configura para que se ejecute una función al seleccionar una fila (vista admin de organismos)

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

		'id'=>'organismos-grid',

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

		'filter'=>$model,

		'template'=>"{items}\n{pager}",		

		'selectionChanged' => 'ChangeHrefs',//El nombre de la función javascript (código anterior) que se ejecuta al seleccionar un organismo		

		'columns'=>$columns

	));

Código de breadcrumbs, para cualquier link para regresar al admin (del create, update u otra vista) hay que pasarle el id del organismo (vista create, update, etc de suborganismos)

$this->breadcrumbs = array (

			"Suborganismos"=>array("suborganismos/admin","id"=>$model->id_organismo),

	);



CONTROLLER

Código del action Admin, se la pasa el id del organismo, y este le asigna el id al model de suborganismos (controller suborganismos)

public function actionAdmin($id) {//Id del organismo

		$model = new Suborganismo( 'search' );

		$model->unsetAttributes (); 

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

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


		$model->id_organismo=$id;//id_organismo es la clave foranea en suborganismos	

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

			'model' => $model 

		) );

	}

Es necesario pasar el Id del organismo a los actions que lo requieren como admin y create, para el action create es (controller suborganismos)

public function actionCreate($id) {//Id del organismo

		$model = new Suborganismo();	

		$model->id_organismo=$id;

		if(isset ( $_POST ['Suborganismo'] )) {

			$model->attributes = $_POST ['Suborganismo'];

			if ($model->save ())

				$this->redirect ( array (

						'admin',

						'id'=>$model->id_organismo,//Se agrega el id del organismo						 

				) );

		}		

		

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

				'model' => $model 

		) );

	}

MODEL

Código search, como id_organismo va a tener valor puesto que se asigno desde el controller, solo mostrara los registros del organismo indicado (model suborganismos)

public function search() {		

		$criteria = new CDbCriteria ();

		$criteria->compare ( 'id_organismo', $this->id_organismo, false );//filtra los suborganismos del organismo

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

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

				

		return new CActiveDataProvider ( $this, array (

				'criteria' => $criteria 

		) );

	}

Solo una corrección, no se debe pasar el id asi array(‘SubOrganismos/admin/’.$model->id) porque si le agregas mas variables o si el formato de la url cambia ya no va a funcionar. Se debe pasar de la siguiente forma array(‘SubOrganismos/admin/’,‘id’=>$model->id).

Si es así, todo exactamente, pero mi pregunta es. para cuando le doy click y me manda al view de suborganismo admin, como hacer para precargar en esta el filtrado del admin. no se si me explique bien.

Supongo que hay que incluir eso dentro de la funcion search como dice a18327. pero no estoy seguro de estar haciendolo bien. si me hace falta algo mas

Hola a18327 como estas, Muchisimas gracias me funciona perfecto, lo unico es que no se porque los filtros de busqueda por los suborganismos que me trajo no me sirven, no se si tengo que hacer algun cambio en en metodo search(). ademas tampoco puedo crear un nuevo suborganismos. el create da una error:

Error 400

Su solicitud es inválida.

Si tienes alguna idea avisame por favor. muchas gracias y disculpa el abuso…

Para crear un nuevo suborganismo le tienes que enviar el id del organismo al que pertenece.


array('label'=>'Nuevo SubOrganismo', 'url'=>array('create','id'=>$model->id_organismo)),

Para los filtros recuerda que el metodo search que puse es de ejemplo no lo puedes copiar y pegar porque no va a funcionar, la unica linea que debes agregar en el search es


$criteria->compare ( 'id_organismo', $this->id_organismo, false );//filtra los suborganismos del organismo

Si pones tu metodo search te daria mas detalles

Lo primero es aclarar algo. yo puse los nombres Organismos y Suborganismos a las tablas como ejemplo para fuera mas facil de entender, pero las tablas se llaman tbl_estructura (id(PK), denominacion, …) y tbl_dependencia (id(PK), idestructura(FK), denominacion, …)

Ahora, La parte del create ya funciona gracias, solo tenia que agregarle el id al que pertenece. :D

Con respecto a lo del search yo solo copie la linea que me dijiste en el "$criteria…", de hecho creo que solo le agregue el false, tambien cambie todos los nombres para que pegaran con mi base de datos. igual siguen sin funcionar los filtros. aqui mi search en el modelo TblDependencias(Suborganismos)




public function search()

	{

		// @todo Please modify the following code to remove attributes that should not be searched.


		$criteria=new CDbCriteria;


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

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

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

		$criteria->compare('idestructura',$this->idestructura,false); //<-- Acá

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

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

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

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

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

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


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}



PD: Perdon por el enrredo, solo que pense que seria mas comprensible para todos con otros nombres :S

El metodo search esta bien ya que filtra por organismos, el problema puede ser porque los atributos no son "safe", o porque en el controller no se le esta pasando el filtro al modelo.

Para que un atributo sea "safe" debes agregarlo a la función rules del modelo en la sección de search


/**

	 *

	 * @return array validation rules for model attributes.

	 */

	public function rules() {

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array (

				array (

						'atributo1, atributo2, atributo3',

						'required' 

				),

				...

				...

				...				

				// The following rule is used by search().

				// @todo Please remove those attributes that should not be searched.

				array (

						'id, idmaximaautoridad, idtipodependencia, ...',//<--Aquí agregas todos los atributos que tienen filtro

						'safe',

						'on' => 'search' 

				) 

		);

	}

Para pasar los filtros al modelo en el controller es como sigue, revisa que este bien el nombre del modelo (SubOrganismo)


public function actionAdmin($id) {//Id del organismo

                $model = new Suborganismo( 'search' );

                $model->unsetAttributes (); 


		//Esta parte es la que toma los valores del filtro (GET) y los pasa al modelo////

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

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

		////////////////////////////////////////////////////////////////////////////////


                $model->id_organismo=$id;//id_organismo es la clave foranea en suborganismos    

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

                        'model' => $model 

                ) );

        }

Ya habia pensado en lo de los rules, pero no veo nada mal ni ahi, ni en el ActionAdmin.




public function accessRules()

	{

		return array(

			array('allow',  // allow all users to perform 'index' and 'view' actions

				'actions'=>array('index','view'),

				'users'=>array('*'),

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

				'actions'=>array('create','update'),

				'users'=>array('@'),

			),

			array('allow', // allow admin user to perform 'admin' and 'delete' actions

				'actions'=>array('admin','delete'),

				'users'=>array('admin'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}


public function actionAdmin($id)

	{

		$model=new TblDependencias('search');

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


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

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


		$model->idestructura=$id;//id_organismo es la clave foranea en suborganismos

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

			'model'=>$model,

		));

	}

Tal vez aqui en mi view admin de TblEstructura? aqui mi vista.


<?php

/* @var $this TblEstructuraController */

/* @var $model TblEstructura */


$this->breadcrumbs=array(

	'Organismos'=>array('index'),

	'Administrar',

);


$this->menu=array(

	//array('label'=>'List TblEstructura', 'url'=>array('index')),

	array('label'=>'Nuevo Organismo', 'url'=>array('create')),

);


/**TENDRA ALGO QUE VER CON ESTA PARTE?**/

/**TENDRA ALGO QUE VER CON ESTA PARTE?**/

/**TENDRA ALGO QUE VER CON ESTA PARTE?**/




/*

Yii::app()->clientScript->registerScript('search', "

$('.search-button').click(function(){

	$('.search-form').toggle();

	return false;

});

$('.search-form form').submit(function(){

	$('#tbl-estructura-grid').yiiGridView('update', {

		data: $(this).serialize()

	});

	return false;

});

");

*/


/**TENDRA ALGO QUE VER CON ESTA PARTE?**/

/**TENDRA ALGO QUE VER CON ESTA PARTE?**/

/**TENDRA ALGO QUE VER CON ESTA PARTE?**/





Yii::app()->getClientScript()->registerScript ( 'ChangeSelectedRowEvent', 'function ChangeHrefs(idRow) {

                id=$("#"+idRow).yiiGridView("getSelection")||0; 

                if(id!=0){

                        var urlTblDependencias="'.Yii::app()->createUrl('tbldependencias/index',array('id'=>'_id_')).'";

                        urlTblDependencias=urlTblDependencias.replace("_id_",id);

                        $("#lnkTblDependencias").attr("href",urlTblDependencias);                    

                }else{

                        $("#lnkTblDependencias").removeAttr("href");                      

                }

        }

        ', CClientScript::POS_END );


?>


<h1>Administrador de Organismos</h1>


<p>

Para ayudar a su busqueda puede usar operadores de comparación tales como  (<b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, <b>&gt;=</b>, <b>&lt;&gt;</b>

o <b>=</b>) al inicio de cada uno de los valores de búsqueda.


<!--<?php echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?> -->

<div class="search-form" style="display:none">

<?php $this->renderPartial('_search',array(

	'model'=>$model,

)); ?>

</div><!-- search-form -->


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

	'id'=>'tbl-estructura-grid',

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

	'filter'=>$model,

	'columns'=>array(

		//'id',

		//'idpadre',

		//'idtipoestructura',

		//'idparroquia', Se cambio para mostrar la relacion con tbl_parroquia

		/*

			array('name'=>'idparroquia0.parroquia',

		   'value'=>'$data->idparroquia0->parroquia',

		   'filter'=>CHtml::activeTextField($model,'varParroquiaTE')

		   ),

		*/

		//'idmaximaautoridad',

		//array('name'=>'idmaximaautoridad'),

		'denominacion',

		array('name'=>'idtipoestructura0.denominacion',

		   'value'=>'$data->idtipoestructura0->denominacion',

		   'filter'=>CHtml::activeTextField($model,'varDenominacionTE')

		   ),

		array('name'=>'idparroquia0.idmunicipio0.idestado0.estado', 

		   'value'=>'$data->idparroquia0->idmunicipio0->idestado0->estado',

		   'filter'=>CHtml::activeTextField($model,'varIdestadoTE')

		   ),

		array('name'=>'idmaximaautoridad0.idpersona0.nombre',

		   'value'=>'$data->idmaximaautoridad0->idpersona0->nombre',

		   'filter'=>CHtml::activeTextField($model,'varIdpersonaTE'),

		   ),

		array('name'=>'idmaximaautoridad0.idpersona0.apellido',

		   'value'=>'$data->idmaximaautoridad0->idpersona0->apellido',

		   'filter'=>CHtml::activeTextField($model,'varIdpersona2TE')

		   ),

		'codigoonapre',

		//'idtipoestructura', Se cambio para mostrar la relacion con tbl_tipoestructura

		/*

		'ubicacionfisica',

		'paginaweb',

		'telefono',

		'estatusreg',

		*/

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>

Segun tu código de la vista los filtros son varDenominacionTE, varIdestadoTE, varIdpersonaTE, varIdpersona2TE, eso quiere decir que en tu model deben existir esas variables, tambien deben estar definidas como "safe" en la función rules del modelo (no la del controller), y debes usarlas en la función search, veo que no usas las variables en la función search asi que ese debe ser el problema

Ok con lo que me dijiste me di cuenta que estuve enredado desde un principio confundi el admin de TblEstructura y el de TblDependencias. acomodando donde deben ir cada uno todo esta corriendo perfectamente :D

Las variables son del admin TblEstructura, algo para mostrar los contenidos de las tablas relacionadas y no las FK que trae la tabla, solo era ese enredo que tenia yo mismo. muchos archivos abiertos a la vez… T_T gracias por todo xD +1 a todas tus respuestas. :)

Muchisimas gracias xD

Buenas tardes a18327

disculpa por revivir un tema viejo pero ya lo he intentado y no encuentro hacerlo, necesito saber si conoces o alguien mas conoce la manera de hacer lo mismo que hice con el admin pero para el index de tbl_dependencia. osea que me traiga las dependencias unicamente del organismo que seleccioné

hasta ahora tengo esto




array('label'=>'Listado de Dependencias del Organismo / Ente', 'url'=>array('tblDependencias/index/','id'=>$model->id)),



llega a la vista de tbl_dependencias index pero el problema es que me trae todas las dependencias de todas los organismos. necesito hacer el filtrado.

intente poner esto en el actionIndex, pero no sirve.




public function actionIndex($id)

	{

		$id = $_GET['id'];

		$dataProvider=new CActiveDataProvider('TblDependencias');


		$dataProvider->getData($id);

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

			'dataProvider'=>$dataProvider,

		));


	}



No puedo manejarlo igual que el admin porque el actionAdmin se maneja con $model y el index con $dataProvider, lo que no se es como hacer para pasarle el id y que me pase un listado solo de las dependencias relacionadas con ese organismo… alguna idea? por favor?

:( necesito ayuda

Creo que quedaria así necesito:

1.- que me digan si lo estoy haciendo bien o mal

2.- si alguien lo necesita tómelo xD




public function actionIndex($id)

	{

		$id = $_GET['id'];

		

		$dataProvider=new CActiveDataProvider('TblDependencias');


		// se agrega la condicion de que haga la busqueda del dataprovider solo 

		//cuando idestructura sea igual al id correspondiente al organo / ente

		$criteria=new CDbCriteria;

		$criteria->condition='idestructura='.$id;

		$dataProvider->setCriteria($criteria);

		

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

			'dataProvider'=>$dataProvider

		));


	}



Yo no veo la necesidad de utilizar el CActiveDataProvider en el controller pues es el mismo caso que al anterior, pero bueno si eso necesitas la logica que tendrias que seguir es la misma que la del metodo search para los GridView, es decir crear un criteria, le agregas los filtros y crear el CActiveDataProvider.


public function actionIndex($id){

    $criteria = new CDbCriteria ();

    $criteria->compare ( 'idestructura', $_GET['id']);

    $dataProvider=new CActiveDataProvider('TblDependencias',array('criteria'=>$criteria));

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

        'dataProvider'=>$dataProvider

    ));

}