visualizzare al meglio le colonne del proprio DB
Il mio problema di oggi è il seguente:
Ho una tabella che contiene una colonna che si chiama isChecked di tipo INT che può contenere 0 oppure 1.
Il risultato che voglio ottenere è quello di chiamare un metodo del tipo
$table->status()
che restituisca "verificato" oppure "da verificare" a seconda del valore contenuto nella colonna.
Naturalmente il tutto deve essere fatto in modo naturale ovvero col minimo sforzo possibile.
Vediamo allora di capire dove andare a mettere il metodo magico che ci trasforma il risultato.
Quando si estraggono i dati da db utilizzando Zend_DB_table, quello che si ottiene indietro è un Rowset, ovvero una collezione di Rows.
Con Zend Framework c'è la possibilità di definire una classe personalizzata di Righe (Rows) che estende quella base in modo da aggiungere i metodi che si desiderano.
Passo 1 - estendere la riga
Per aggiungere nuovi metodi alla riga si crea, quindi, una classe che estende Zend_Db_Table_Row_Abstract
nel mio caso uso la seguente:
<?php
class Naturalads_WebsiteRow extends Zend_Db_Table_Row_Abstract
{
/**
* Find the Row in the current Rowset with the
* greatest value in its 'updated_at' column.
*/
public function status()
{
$output = ($this->isChecked == 0)? "da verificare":"verificato";
return $output;
}
}
la classe la salvo naturalmente in library/Naturalads/WebsiteRow.php dove l'autoloader la può trovare comodamente
Passo 2 - aggiungere la classe al modello
Occorre aggiungere al model la classe di riga creata nel passo 1. Questo è molto più semplice del previsto, basta infatti aggiungere al proprio modello una variabile protetta:
protected $_rowClass = 'Naturalads_WebsiteRow';
in pratica io uso il seguente modello che basta e avanza per i miei scopi:
<?php
class Website extends Zend_Db_Table {
protected $_name = 'Websites';
protected $_rowClass = 'Naturalads_WebsiteRow';
}
devo dire che il modello lo salvo come al solito in models/Website.php
Passo 3 - Usare il modello
Adesso il modello è pronto per l'uso e contiene la mia estensione di classe e il mio metodo. L'unica cosa che mi manca è solo richiamarlo. Vediamo come è possibile istanziare il tutto nel controller e poi visualizzarlo in una view:
Nel mio controller posso utilizzare qualcosa del genere
...
$website = new Website();
$this->view->assign('websites', $website->fetchAll()); // fetchAll's signature is unmodified
...
quindi nella view uso qualcosa del genere per richiamare il mio metodo personale:
<?php foreach($this->websites as $website) : ?>
<tr>
<td><?php echo $this->escape($website->url);?></td>
<td><?php echo $this->escape($website->status());?></td>
</tr>
<?php endforeach; ?>
e adesso...
Forse non è velocissimo, ma in questo modo posso 'giocare' con tutte le colonne direttamente nel modello di dati, aggiungere colonne virtuali e richiamare il tutto sempre come metodi dalla view senza dover toccare il controller in alcun modo.
Un ottima cosa per la manutenzione del progetto. Se un domani dovrò gestire il nuovo stato "verificato senza successo", basterà inserire il valore -1 nel campo isChecked e modificare il metodo status(). Tutta l'applicazione continuerà a funzionare e a mostrare il nuovo stato senza problemi.
1 commento:
Io preferirei una relazione di tipo has-a invece che is-a fra i modelli e le istanze di *_Row. Questo rende le righe riutilizzabili anche per altri scopi senza che debbano corrispondere a un entità ben definita.
Ad esempio taggare un post di un form sotto una categoria corrisponde a una riga di una certa tabella. Può essere un modello sotto un certo punto di vista, in quanto il tag può avere alcune operazioni da svolgere (immagina una tag cloud per esempio), ma anche solamente una riga che viene letta dalla classe che gestisce la categoria o il singolo post. Inoltre preferisco questo approccio perché astrae il modello dal database e si può dargli l'interfaccia più appropriata (che non sempre è save(), eccetera..).
Posta un commento