Mam następujący problem. Chciałem sporzadzić formularz do edytowania uprawnien dla danej grupy użytkowników. Struktura tabel w/g AuthManager. Zrobiłem formularz w którym można zmienić nazwe grupy, opis, oraz zaznaczyć (lub odznaczyć) uprawnienia:
formularz:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'grupy-form',
'enableAjaxValidation'=>true,
)); ?>
<p class="note">Pola oznaczone <span class="required">*</span> są wymagane.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'nowaNazwa'); ?>
<?php echo $form->textField($model,'nowaNazwa',array('size'=>60,'maxlength'=>128)); ?>
<?php echo $form->error($model,'nowaNazwa'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'nowyOpis'); ?>
<?php echo $form->textField($model,'nowyOpis',array('size'=>60)); ?>
<?php echo $form->error($model,'nowyOpis'); ?>
</div>
<div class="row">
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'uprawnienia-grupy-grid',
'dataProvider'=>$dataProvider,
'selectableRows'=>$dataProvider->getItemCount(),
'columns'=>array(
array(
'name'=>'id',
'value'=>'$this->grid->dataProvider->getPagination()->getOffset()+$row+1',
'header'=>'Nr.',
'filter'=>false,
),
'description',
array(
'class'=>'myCheckBoxColumn',
'name'=>'upraw',
'value'=>'$data->name',
'checked'=>
isset($_GET['name'])?'AuthItemChild::model()->exists("parent=:parent and child=:child", array(":parent"=>"'.$_GET['name'].'",":child"=>$data->name ))':'false',
),
)
));
?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Zatwierdź'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
Do tego stworzyłem klase modelu CFormModel (UprawnieniaForm)
public $nazwa;
public $opis;
public $nowaNazwa;
public $nowyOpis;
public $uprawnienia=array();
.
.
.(reszta modelu)
.
.
public function save(){
$auth = Yii::app()->authManager;
$grupa = $auth->getAuthItem($this->nazwa);
//edycja istniejącej grupy else tworzenie nowej
if(isset($grupa)){
//sprawdz czy istniejace w bazie powiazania sa zgodne z nowymi, jesli nie to usun
$records = AuthItemChild::model()->findAllByAttributes(array('parent'=>$this->nazwa));
if(!empty($records)){
foreach($records as &$rec){
$znalazl = false;
foreach($this->uprawnienia as &$upr){
if($rec->child==$upr){
$znalazl = true;
break;
}
}
if(!$znalazl){
$grupa->removeChild($rec->child);
}
unset($upr);
}
unset($rec);
}
//dodaj nowe uprawnienia, ale tylko te ktore nie sa juz zapisane
foreach($this->uprawnienia as &$upr){
if(!empty($records)){
$znalazl = false;
foreach($records as &$rec){
if($upr==$rec->child){
$znalazl = true;
break;
}
}
if(!$znalazl){
$grupa->addChild($upr);
}
unset($rec);
}
else{
$grupa->addChild($upr);
}
}
unset($upr);
return true;
}
//tworzenie nowej grupy
else{
$grupa = $auth->createRole($this->nazwa, $this->opis);
if(!empty($this->uprawnienia)){
foreach($this->uprawnienia as &$upr){
$grupa->addChild($upr);
}
}
return true;
}
return false;
i w kontrolerze wywołuje taką akcje
public function actionEdytujGrupe(){
if(AuthItem::model()->exists(array('name'=>$_GET['name']))){
$model = new UprawnieniaForm;
$model->nazwa = $_GET['name'];
if(isset($_POST['UprawnieniaForm'])){
$model->nowaNazwa = $_POST['UprawnieniaForm']['nowaNazwa'];
$model->nowyOpis = $_POST['UprawnieniaForm']['nowyOpis'];
if(isset($_POST['upraw'])){
$model->uprawnienia = $_POST['upraw'];
}
else $model->uprawnienia = array();
if($model->save()){
$modelAI = AuthItem::model()->findByAttributes(array('name'=>$model->nazwa));
$modelAI->setAttribute('name',$model->nowaNazwa);
$modelAI->setAttribute('description',$model->nowyOpis);
if($modelAI->update()){
//echo $modelAI->description;
$this->redirect(array('grupy'));
}
}
}
else{
$modelAI = AuthItem::model()->findByAttributes(array('name'=>$_GET['name']));
$model->nowaNazwa = $_GET['name'];
$model->nowyOpis = $modelAI->description;
}
$dataProvider=new CActiveDataProvider(new AuthItem,
array(
'criteria'=>array(
'condition'=>'type<2',
),
'pagination'=>array(
'pageSize'=>40,
),
)
);
$this->render('edytujGrupe',array('model'=>$model,'dataProvider'=>$dataProvider, 'name'=>$model->nazwa));
}
else{
throw new CHttpException(404,'Nie ma takiej grupy.');
}
}
Wszystko działa ładnie jak robię pojedynczo rzeczy, np. zmieniam uprawnienia, zmienia się, zmieniam opis, zmienia się, zmieniam nazwę, zmienia się.
Wysypuje się w sytuacji kiedy chce zmienić i nazwę i uprawnienia. W akcji wyraźnie najpierw wykonuje oeracje save na rekordzie jeszcze w starej nazwie, dopiero potem zmieniam nazwe rekoru, a wrezultacie dostaje taki błąd:
I do tego powstaje nowy rekord w bazie o wprowadzonej nowej nazwie i bez uprawnien.