Devo creare una causale contabile (caucon), che ha dei righi collegati (CauconPiacon), dove piacon significa piano dei conti.
Ho 2 model, 2 controller, alcune View.
e un codice.
public function actionCreate() {
$model = new ContabCaucon;
//inizializzo i righi dare e avere del piano dei conti interessati dalla causale
$righi = array();
$righi['D'] = array();
$righi['A'] = array();
//creo un nuovorigo vuoto, da usare per inserire i righi
$newrigo = new ContabCauconPiacon();
$newrigo->model()->scomponi();
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
//se c'è un post
if (isset($_POST['ContabCaucon'])) {
//carico la causale contabile
$model->attributes = $_POST['ContabCaucon'];
//se ho detto di cancellare un rigo lo tolgo subito dal POST['righi']
if(Yii::app()->input->post('del')) {
//elimino un rigo
unset ($_POST['righi'][Yii::app()->input->post('del')]);
}
//se ci sono righi mi popolo gli array righidare e righiavere di cui sopra
if (Yii::app()->input->post('righi')) {
foreach ($_POST['righi'] as $key => $rig) {
//nuova associazione piano dei conti - causale contabile
$rigo = new ContabCauconPiacon();
$rigo->attributes = $rig;
$rigo->scomponi();
//inserimento del rigo nell'array righi corrispondente
$righi[$rigo->mov][] = $rigo;
}
}
//se ho confermato l'inserimento di un nuovo rigo
if (Yii::app()->input->post('newrig')){
//nuova associazione piano dei conti - causale contabile
$rigo = new ContabCauconPiacon();
$rigo->attributes = $_POST['newrigo'];
$rigo->scomponi();
//lo piazzo all'inizio dell'array rigo corrispondente
array_unshift($righi[$rigo->mov], $rigo);
unset($rigo);
}
else if(Yii::app()->input->post('del')) {
//qui ripeto se c'è il del, senza azioni stavolta... non mi piace!
} else {
//in caso contrario è un salvataggio
if ($model->save()){
foreach ($righi as $tip=>$rigo)
{$rigo->save();}
$this->redirect(array('view', 'id' => $model->id));}
}
}
$this->render('create', array(
'model' => $model,
'newrigo' => $newrigo,
'righi' => $righi
));
}
Quello che non mi piace è… la mancanza di eleganza: ripetere il check sul del è inutile e noioso in teoria, ma in pratica se non lo metto mi valida sempre il form come se salvassi anche se ho cancellato una riga…
Soluzione 1: invece di creare 2 array righi dare/avere metto tutto in righi e invece di eliminare dal post elimino dall’array righi.
Soluzione 2: mi accontento
Soluzione 3: Yiiresources! vale a dire: Oh voi pratici e potenti conoscitori di Yii aiutatemi a abberverarmi alla fonte di conoscenza delle mille mila soluzioni già pensate da YII!
La compressione dei campi non è una buona pratica. Infatti hai dovuto spiegarcelo. Potresti usare il nome “causale_contabile” e invece decidi di usare caucon. C’è una ragione particolare? Piacon potrebbe essere piano_dei_conti. Anche gli array: come mai non li chiami ‘dare’ o ‘avere’ e li comprimi in D oppure A. Non è più complicato!?
ma lavorando da solo mi sono ridotto a concentrare…
Ecco qui una esplicazione
public function actionCreate() {
$model = new Causale_contabile;
//inizializzo i righi dare e avere del piano dei conti interessati dalla causale
$righicausale= array();
$righicausale['Dare'] = array();
$righicausale['Avere'] = array();
//creo un nuovorigo vuoto, da usare per inserire i righi
$newrigo = new RigoCausale();
//se c'è un post
if (isset($_POST['Causale_contabile'])) {
//carico la causale contabile
$model->attributes = $_POST['Causale_contabile'];
//se ho detto di cancellare un rigo lo tolgo subito dal POST['righi']
if(Yii::app()->input->post('del')) {
//elimino un rigo
unset ($_POST['righicausale'][Yii::app()->input->post('del')]);
}
//se ci sono righi mi popolo gli array righi dare e righiavere di cui sopra
if (Yii::app()->input->post('righicausale')) {
foreach ($_POST['righicausale'] as $key => $rig) {
//nuova associazione piano dei conti - causale contabile
$rigo = new RigoCausale();
$rigo->attributes = $rig;
//inserimento del rigo nell'array righi corrispondente
$righicausale[$rigo->tipomov][] = $rigo;
}
}
//se ho confermato l'inserimento di un nuovo rigo
if (Yii::app()->input->post('newrig')){
//nuova associazione piano dei conti - causale contabile
$rigo = new RigoCausale();
$rigo->attributes = $_POST['newrigo'];
//lo piazzo all'inizio dell'array rigo corrispondente
array_unshift($righicausale[$rigo->tipomov], $rigo);
}
else if(Yii::app()->input->post('del')) {
//qui ripeto se c'è il del, senza azioni stavolta... non mi piace!
} else {
//in caso contrario è un salvataggio
if ($model->save()){
foreach ($righicausale['Dare'] as $tip=>$rigo){$rigo->save();}
foreach ($righicausale['Avere'] as $tip=>$rigo){$rigo->save();}
$this->redirect(array('view', 'id' => $model->id));}
}
}
$this->render('create', array(
'model' => $model,
'newrigo' => $newrigo,
'righicausale' => $righicausale
));
}
questa la view:
<table>
<!-- inserimento dati della causale (descrizione, abbreviazione etc)-->
</table>
<fieldset><legend>Nuovo Rigo</legend>
<?php echo $this->renderPartial('/Rigocausale/_form_nuovorigo', array('model'=>$newrigo)); ?></fieldset>
<fieldset><legend>Righi</legend> <table>
<thead>
<th> <?php echo CHtml::activeLabelEx($model, 'piano_dei_conti'); ?></th>
<th> <?php echo CHtml::activeLabelEx($model, 'tipomovimento'); ?></th>
<th><?php echo CHtml::activeLabelEx($model, 'azione'); ?></th>
<th>
<?php echo CHtml::activeLabelEx($model, 'importo'); ?></th>
</thead>
<tbody><?php
$i=1;
//per ogni rigo richiamo una view contente una singola riga, con il suo bottone 'del' per eliminarla.
foreach ($righicausale['Dare'] as $rigo ) {
echo $this->renderPartial('/Rigocausale/_form_row', array('model'=>$rigo, 'rignum'=>$i));
$i++;
}
?><?php
foreach ($righicausale['Avere'] as $rigo ) {
echo $this->renderPartial('/Rigocausale/_form_row', array('model'=>$rigo, 'rignum'=>$i));
$i++;
}
?></tbody>
</table></fieldset>
<?php $this->endWidget(); ?>
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
A ma … tu vuoi solo sapere se c’è un modo più elegante per scrivere quel codice? La prima cosa che mi viene da dire è che io al posto tuo indenterei meglio il codice. In genere è una cosa che fatta a mano richiede molto tempo. Infatti uso Netbeans. Quando premo Ctrl+Alt+F indenta tutto il codice. Tutto. Così è tutto sempre ordinato.
Riguardo alla tua domanda. Sono dell’idea che se va, ed il tuo scopo è che vada, allora non c’è bisogno di rifattorizzare nulla. Se invece vuoi proprio concentrarti sulla scrittura di un codice pulito, beh, cancella tutto e riscrivi. Non scherzo =). In genere la seconda volta viene sempre meglio.