[Risolto] Vista Relazione Molti A Molti (View Many To Many)

Ciao a tutti e prima di tutto vi ringrazio per il supporto che fornite alla comunità di yii in italiano.

Vengo al problema:

Ho una relazione molti a molti.

Sto cercando di realizzare un view ( insert, update, delete).

My link

Mi piacerebbe fare una vista gridview padre figlio come indicato nel seguente wiki:

View Padre Figlio

Putroppo ci sono solo spezzoni di codice e manca l’esempio completo e visto che sono nuovo di yii non sono riuscito a realizzare l’esempio del wiki.

Avete qualche esempio di codice pronto ?

Oppure come avete trattato le view di relazioni molti a molti ?

Ho girato quasi tutto il forum italiano ma non ho trovato nulla, e quindi una soluzione sarebbe utile a tutta la comunità di YII.

Grazie a tutti.

PS: Come esempio di tabelle DB potete prendere quello del wiki indicato sopra.

La tua domanda mi sembra un po’ confusa. Tu vorresti fare un crud, per una relazione molti a molti. Una relazione di tipo padre/figlio non la vedo esattamente come molti a molti. Un figlio ha un solo padre. Potresti spiegare meglio qual’è il problema che stai cercando di risolvere?

Cerco di spiegarmi con un esempio.

ho tre tbl Categoria, Prodotti, CategoriaProdotti ( vedi file allegato)

Un prodotto può appartenere a più categoria, come una categoria può appartenere a più prodotti.

Valori Categoria:

  • Surgelati

  • Fresco

±-----±--------+

| id | categoria |

±---------------+

| 1 | Surgelati |

| 2 | Fresco |

±----------------|

Valori Prodotti:

[*]Carne

[*]Pesce

[/list]

±-----±--------+

| id | prodotti |

±---------------+

| 1 | carne |

| 2 | pesce |

±----------------|

tbl_ categoria prodotti:

±-----±--------±--------+

| id | id_prodot | id_categ |

±---------------±---------

| 1 | 1 | 1 |

| 2 | 1 | 2 |

| 3 | 2 | 1 |


Per gestire la caegoria posso fare una vista semplice e un form per registrare le categorie ovvero un crud generato con gii.

Per gestire i prodotti non mi basta una view semplice con un form perchè devo poter inserire molteplici categoria. Quindi a me interessa come poter gestire la view Prodotti per fare le operazioni crud ( insert, update, delete)

Spero di essere stato chiaro3181

Schermata 09-2456179 alle 13.25.40.png

Chiaro sei stato chiaro. Io ti suggerire di usare un po’ di ajax. In pratica fai un form che invia una post in background e come funziona di callback ricarica lo stesso form e l’elenco delle chiavi esterne.

Hai un esempio di codice? 3182

Schermata 09-2456179 alle 15.43.55.png

Mi piacerebbe realizzare una cosa del genere 3182

Schermata 09-2456179 alle 15.43.55.png

Oppure dovrei usare un’estensione tipo http://www.yiiframework.com/extension/manymanyajaxcrudadmin ma non mi piace molto.

Con esempio di codice intendevo PHP. Ma va bene lo stesso. Adesso mi serve di capire che cosa ti manca per arrivare ad implementare qualche cosa come in quell’immagine. Poi posso provare ad aiutarti. Se dovessi farlo io, come ti dicevo, andrei dritti verso una soluzione con ajax, e mi scriverei le view del form, dell’elenco dei contatti, qualche richiesta json per i dati già inseriti, molto jQuery per gestire la parte asincrona (con asincrona intendo ajax).

Il mio problema era a monte, ovvero capire come si gestiscono le relazioni molti e molti con Yii. Penso di averle capite e vi posto un esempio completo che ho realizzato dopo un fine settimana di studio. ( sono alla prime armi con yii :wink: ).

Nulla di difficile e spero sia utile alla comunità.

In questo primo esempio spiegherò la lettura delle relazioni molti a molti. Nei prossimi giorni spero di fare qualche esercizio con le insert ed update e postare la soluzione.

Abbiamo tre tabelle: utenti,utenti_permessi,permessi

3185

er_test.JPG

I valori della tabella permessi possono essere: lettura,scrittura,modifica, etc

Un utente appartiene a più permessi come un permesso appartiene a più utenti.




--

-- Struttura della tabella `permessi`

--


CREATE TABLE IF NOT EXISTS `permessi` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `nome` varchar(40) NOT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;


--

-- Dump dei dati per la tabella `permessi`

--


INSERT INTO `permessi` (`id`, `nome`) VALUES

(1, 'insert'),

(2, 'read'),

(5, 'execute'),

(6, 'full');


--

-- Struttura della tabella `utenti`

--


CREATE TABLE IF NOT EXISTS `utenti` (

  `id` int(11) NOT NULL,

  `nome` varchar(45) DEFAULT NULL,

  `cognome` varchar(45) DEFAULT NULL,

  `id_amministratore` int(11) NOT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1;


--

-- Dump dei dati per la tabella `utenti`

--


INSERT INTO `utenti` (`id`, `nome`, `cognome`, `id_amministratore`) VALUES

(1, 'paolo', 'rossi', 1),

(2, 'vincenzo', 'nuoti', 0),

(3, 'Pippo', 'Pippo', 1);


--

-- Struttura della tabella `utenti_permessi`

--


CREATE TABLE IF NOT EXISTS `utenti_permessi` (

  `utenti_id` int(11) NOT NULL,

  `permessi_id` int(11) NOT NULL,

  PRIMARY KEY (`utenti_id`,`permessi_id`),

  KEY `fk2` (`permessi_id`),

  KEY `fk1` (`utenti_id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1;


--

-- Dump dei dati per la tabella `utenti_permessi`

--


INSERT INTO `utenti_permessi` (`utenti_id`, `permessi_id`) VALUES

(1, 1),

(1, 2),

(3, 5),

(3, 6);


--

-- Limiti per le tabelle scaricate

--


--

-- Limiti per la tabella `utenti_permessi`

--

ALTER TABLE `utenti_permessi`

  ADD CONSTRAINT `utenti_permessi_ibfk_3` FOREIGN KEY (`permessi_id`) REFERENCES `permessi` (`id`),

  ADD CONSTRAINT `utenti_permessi_ibfk_1` FOREIGN KEY (`utenti_id`) REFERENCES `utenti` (`id`);







Possiamo creare velocemente i model della classe Utenti e Permessi con gii.

Nel model Utenti ( se gii non l’ha generato) aggiungere:




public function relations()

	{

	

		return array(

				'permessis' => array(self::MANY_MANY, 'Permessi', 'utenti_permessi(utenti_id, permessi_id)'),

		);

	}




Nella Model Permessi aggiungere :




public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		

		return array(

			'utentis' => array(self::MANY_MANY, 'Utenti', 'utenti_permessi(permessi_id, utenti_id)'),

		);

	}




Velocemente vi mostro come scorrere i record di object.

Nella view SiteController inserite la seguente azione che mostra gli utenti appartenente ai permessi e viceversa:





public function actionTestManyToMany1()

	{

		// findAll restituisce un record di oggetti.

		$permessi = Permessi::model()->findAll();

		$utenti = Utenti::model()->findAll();

	

		foreach($permessi as $permesso)

		{

			echo $permesso->nome . " Questo permesso associato a  " . count($permesso->utentis) . " utenti. Essi sono:<br />";

			foreach($permesso->utentis as $utente)

			{

				echo $utente->nome . "<br />";

			}

			echo "<br />";

		}

	

		echo "<hr />";

	

		foreach($utenti as $utente)

		{

				

			echo $utente->nome . " sono associati n= " . count($utente->permessis) . " permessi. Essi sono :<br />";

			foreach($utente->permessis as $permesso)

			{

				echo $permesso->nome . "<br />";

			}

			echo "<br />";

		}

	}






Esempio di query:

Trova tutti i permessi associati ad un utente con id=1 e il cui amministratore_id=1





public function actionTestManyToMany()

	{

		// findAll restituisce un record di oggetti.

		$permessi = Permessi::model()->findAll();

		$criteria=new CDbCriteria;

		$criteria->select='*';

		$criteria->condition='id_amministratore=:_id AND id=:idp';

		$criteria->params=array(':_id'=>1,':idp'=>1);

		$utenti=Utenti::model()->findAll($criteria);

	

		foreach($permessi as $permesso)

		{

			echo $permesso->nome . " Questo permesso associato a  " . count($permesso->utentis) . " utenti. Essi sono:<br />";

			foreach($permesso->utentis as $utente)

			{

				echo $utente->nome . "<br />";

			}

			echo "<br />";

		}

	

		echo "<hr />";

	

		foreach($utenti as $utente)

		{

				

			echo $utente->nome . " sono associati n= " . count($utente->permessis) . " permessi. Essi sono :<br />";

			foreach($utente->permessis as $permesso)

			{

				echo $permesso->nome . "<br />";

			}

			echo "<br />";

		}

	}




Giorno 11-09-2012

Lavorare con i dataprovider - CActiveDataProvider

Negli esempi precedenti abbiamo lavorato con i CActiveRecord.

Lavorare con gli oggetti di tipo CActiveRecord è utile quando usiamo

nelle viste zii.widgets.CListView e zii.widgets.CDetailView.

Velocementi con gii generiamo il CRUD del model Utenti.

Nell’actionIndex di UtentiController abbiamo una istanza di CActiveRecord




public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Utenti');

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

			'dataProvider'=>$dataProvider,

		));

	}



il dataprovider viene passato alla vista index di Utenti.

Nella vista utenti index troviamo un zii.widgets.CListView a cui viene passato il dataprovider.

Come ItemView troviamo il _view.php

Noi per vedere tutti i permessi di un utente dobbiamo lavorare su quest’ultimo.

utenti/_viem.php




//visualizzaziamo tutti i permessi associati ad un utente

if (count($data->permessis) > 0): 

	?>

    <div align="left">

      <b>Pemessi:</b> 

      

      <?php

      // scorro tutti i permessi

      foreach ($data->permessis as $item) : ?>

      <ul>

        <li><?php echo $item->nome; ?></li>

       </ul>

      <?php endforeach; ?>

    </div>

  <?php endif; ?>




Vaediamo anche la relazione molti a molti nel componente zii.widgets.CDetailView

usato nella vista utenti/view




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

	'data'=>$model,

	'attributes'=>array(

		'id',

		'nome',

		'cognome',

	    array('label'=>'Permessi',

				'type'=>'raw',

				   

				  'value'=>$model->RelatedPermessis, // la classe va inserita nel model Utenti

					

				),

        

			),

		

		)); ?>






Model/Utenti





	public function getRelatedPermessis()

	{

		$out=CHtml::listData($this->permessis,'id','nome');

		$puntolista = '<ul>';

		foreach($out as $key=>$value) {

			

			//$puntolista .= sprintf('<li>%s</li>', CHtml::link($value, array('artikel/view', 'id' => $key)));

			$puntolista .= sprintf('<li>%s</li>',$value);

	

		}

		$puntolista .= '</ul>';

		return $puntolista;

	}

	




Leggere - CheckBoxList Many to Many

Se volessimo visualizzare una lista di checkbox (checkboxlist) modificare la precendente classe

come di seguito:

Model/Utenti




public function getRelatedPermessisCheckBox()

	{

		$listachiave=array();

		$lista=CHtml::listData($this->permessis,'id','nome');

		foreach($lista as $key=>$value){

			$listachiave[]=$key;

		}

		$out=CHtml::checkBoxList("ListaPermessi",$listachiave, CHtml::listData(Permessi::model()->findAll(), 'id', 'nome'),array('disabled'=>true));

		return $out;

	}




[i][b]

[font="Arial Black"]INSERT ED UPDATE[/font] [/b][/i]

Per la insert ed update ci avvaliamo di un componente che ci facilita di molto la vita.

Si chiama CSaveRelationBehavior.php Download

Scaricate il componente e inseritelo nella cartella components.

Inserite in config/main.php




// autoloading model and component classes

	'import'=>array(

		'application.models.*',

		'application.components.*',

		'application.extensions.CAdvancedArBehavior'

	),


 



Nel model Utenti.php inserire le relazioni e il behaviors:




public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

				'permessis' => array(self::MANY_MANY, 'Permessi', 'utenti_permessi(utenti_id, permessi_id)'),

				//'services' => array(self::MANY_MANY, 'Service', 'LibraryService(libraryID, serviceID)'),

				'utentipermessis'=>array(self::HAS_MANY, 'utenti_permessi', 'utenti_id'),

		);

	}

	

	public function behaviors(){

		return array(

				'CSaveRelationsBehavior' => array(

						'class' => 'CSaveRelationsBehavior',

						'relations' => array(

								'utentipermessis'=>array("message"=>"Please, check the permessi"),

								//'libraryComments'=>array("message"=>"Please, check the comments"),

								//'services'=>array("message"=>"Please, check the services")

						)

				)

		);

	}






Per l’insert nella view _form inserire:





	<?php 

	

	$selected_permission = array(); 

	foreach($model->permessis as $permessi) array_push($selected_permission, $permessi->id);

	//print_r($selected_services);

	?>

	

   

	<div class="row">

        <?php echo $form->labelEx($model, 'permessi'); ?>

        <?php // echo $form->checkBoxList($model, 'permessis', CHtml::listData(Permessi::model()->findAll(), 'id', 'nome'), array('labelOptions' => array('style' => 'display:inline'))); ?>

       <?php echo CHtml::checkBoxList('Permessi', $selected_permission , CHtml::listData(Permessi::model()->findAll(), 'id', 'nome'),array('template'=>'{input} {label}','labelOptions'=>array('style'=>'display:inline;'))); ?>

        <?php echo $form->error($model, 'colors'); ?>

	</div>




Nel conttroller Utenti l’actione Create diventa:




	public function actionCreate()

	{

		$model=new Utenti;


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['Utenti']))

		{

			

		//var_dump($_POST['Utenti']['permessis']);

			//exit;

			

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

			$model->setRelationRecords('permessis',is_array(@$_POST['Permessi']) ? $_POST['Permessi']: array());

			

			if($model->save())

				$this->redirect(array('view','id'=>$model->id));

		}


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

			'model'=>$model,

		));

	}







ACTION UPDATE

Per l’update

sempre nel controller Utente




public function actionUpdate($id)

	{

		$model=$this->loadModel($id);


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['Utenti']))

		{

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

			$model->setRelationRecords('permessis',is_array(@$_POST['Permessi']) ? $_POST['Permessi']: array());

			if($model->save())

				$this->redirect(array('view','id'=>$model->id));

		}


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

			'model'=>$model,

		));

	}









dove loadModel




	public function loadModel($id)

	{

		$model=Utenti::model()->findByPk($id);

		if($model===null)

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

		return $model;

		

	}







Spero che questo tutorial vi sia stato utile.

Ciao A tutti