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 ).
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