.: HosiriS :.

Informatica e non solo

Unico form per gestire molti model con CakePHP

Posted by hosiris su gennaio 15, 2011

Queste ultime settimane mi hanno visto impegnato nel cercare una soluzione al seguente problema: avendo due form, come posso ridurre al minimo il numero di click per effettuare degli inserimenti sequenziali?
Ho provato di tutto, dai redirect ad Ajax… fin quando ho avuto la semplice idea di unire i due form in unico.
CakePHP fornisce un metodo (saveAll()) che ci permette di effettuare salvataggi su più model, come in una transazione… purtroppo quando lavoriamo con relazioni HABTM questa soluzione non funziona.
Come risolvere allora? La soluzione arriva da un altro metodo: requestAction() che ci permette di fare richieste a controller diversi da quello attuale. Ma passiamo alla pratica; riprendiamo le nostre tabelle users e groups e facciamo in modo che il form di inserimento users contenga anche il form per il group.
Apriamo la vista per l’azione add ed inseriamo il seguente:

<?php echo $this->Form->create('User');?>
  <fieldset>
    <legend><?php __('Add User'); ?></legend>
  <?php
    echo $this->Form->input('name');
    echo $this->Form->input('Group');
    echo $this->Form->input('AddGroup',array('type'=>'checkbox','label'=>'Aggiungi Gruppo'));
    ?><fieldset><?php
    echo $this->Form->input('Group.name');
    ?></fieldset><?php
  ?>
  </fieldset>
<?php echo $this->Form->end(__('Submit', true));?>

Abbiamo aggiunto una checkbox ed un campo di input. Lo scopo è quello di far scegliere all’utente se voler aggiungere un ulteriore gruppo oppure usare quelli esistenti. Allora nel controller dobbiamo inserire una if e la chiamata all’azione del controller groups:

function add() {
  if (!empty($this->data)) {
    /*
     * Nel caso si decida di aggiungere un nuovo gruppo l'if sarà vero
     */
    if($this->data['User']['AddGroup']){
      // Salvo i dati che mi servono in una variabile di sessione
      $this->Session->write('groupname',$this->data['Group']['name'];
      // Eseguo la richiesta
      $groups = $this->requestAction(array('controller'=>'groups','action'=>'savefrom'));
      // Aggiungo l'id dell'ultimo gruppo inserito nell'array di inserimento dell'user
      $this->data['Group']['Group']['0'] = $this->Session->read('idgroup');
    }
    /*
     * Eseguo il normale inserimento dell'user
     */
    $this->User->create();
    if ($this->User->save($this->data)) {
      $this->flash(__('User saved.', true), array('action' => 'index'));
    } else {
    }
  }
  $groups = $this->User->Group->find('list');
  $this->set(compact('groups'));
}

A questo punto dobbiamo creare l’azione savefrom nel controller groups. Questa action non farà altro che leggere la variabile di sessione generata, effettuare l’inserimento e restituire l’ultimo id inserito:

function savefrom(){
  $data['Group']['name']=$this->Sessione->read('groupname');
  $this->Group->save($data);
  $this->Session->write('idgroup',$this->Group->getLastInsertId());
}

Et voilà… il gioco è fatto! Adesso è sufficiente aggiungere un effetto javascript che faccia apparire il “sottoform” solo dopo aver spuntato il box di aggiunta.
Sono sicuro che è la soluzione meno elegante esistente, ma questo è quello che il mio cervelletto ha prodotto! Se qualcuno vuole proporre soluzioni migliori renderebbe un grosso favore alla società.

PS: Grazie ad Allanon per la dritta sulla funzione😀

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

 
%d blogger cliccano Mi Piace per questo: