venerdì 28 settembre 2007

Joomla 1.5: Continuiamo lo Sviluppo del Componente di Esempio

Riprendiamo il lavoro sul componente di esempio per Joomla 1.5.

Per chi se le fosse perse ecco i link alle puntate precedenti

Al punto in cui siamo arrivati l'area di amministrazione del componente manca di tutta una serie di funzioni standard che devono essere presenti in ogni componente che si rispetti. E questo sarà pure solo un componente di esempio, ma al rispetto ci tiene!

Inizieremo con l'aggiungere una funzione standard di paginazione record alla tabella per la visualizzazione dei dati inseriti dall'utente tramite il modulo di immissione dati.

Model

La prima parte da modificare è il codice della classe relativa all'oggetto Model del backend.

Riporto per chiarezza tutto il codice della classe MyFormModelMyForm. Se (con molta pazienza!) avete costruito il componente seguendo passo passo gli articoli precedenti potete aggiungere o modificare solo le parti in blu, le altre le dovreste avere, una controllatina non fa male però.

Il file è myform.php in
.../administrator/components/com_myform/models

class MyFormModelMyForm extends JModel {
  var $_total = null;
  var $_pagination = null;
  function __construct() {
    parent::__construct();
    global $mainframe, $option;

    $limit = $mainframe->getUserStateFromRequest('global.list.limit', 
    'limit', $mainframe->getCfg('list_limit'), 'int');
    $limitstart = $mainframe->getUserStateFromRequest($option.
    'limitstart', 'limitstart', 0, 'int');

    $this->setState('limit', $limit);
    $this->setState('limitstart', $limitstart);
  }
  function _buildQuery() {
    $query = ' SELECT * FROM #__myform ';
    return $query;
  }
  function getTotal() {
    if (empty($this->_total)) {
      $query = $this->_buildQuery();
      $this->_total = $this->_getListCount($query);
    }
    return $this->_total;
  }
  function getPagination() {
    if (empty($this->_pagination)) {
      jimport('joomla.html.pagination');
      $this->_pagination = new JPagination($this->getTotal(),
      $this->getState('limitstart'), $this->getState('limit'));
    }
    return $this->_pagination;
  }
  function getData() {
    $query = $this->_buildQuery();
    $pagination = $this->getPagination();
    $data = $this->_getList($query, $pagination->limitstart,
    $pagination->limit);
    return $data;
  }
}

Andiamo con ordine.
La funzione di paginazione record ha bisogno di due parametri fondamentali: il numero di record da visualizzare per ogni pagina (limit) e il numero della pagina su cui ci si trova (limitstart).

Il valore di questi parametri varia quando l'utente si sposta di pagina in pagina o modifica il numero delle righe da visualizzare con la lista di selezione in fondo alla tabella.

Il costruttore della classe utilizza il metodo getUserStateFromRequest() per recuperare i valori di limitstart e limit.

Funzioni che gestiscono queste, così definite nella documentazione ufficiale, variabili di stato utente (user state variable) si incontrano spesso esaminando il codice di componenti: getUserState, setUserState, getUserStateFromRequest, tutte definite in .../libraries/joomla/application/application.php come metodi della classe JApplication.

Il termine user state variable può confondere. Tutto sommato si tratta però di un concetto semplice: sono variabili che mantengono il loro valore attraverso diverse esecuzioni dello script perché sono salvate come variabili di sessione.

L'istruzione

$limit = $mainframe->getUserStateFromRequest('global.list.limit', 
  'limit', $mainframe->getCfg('list_limit'), 'int');

svolge le seguenti operazioni.

Legge il valore della variabile di stato (o se vi torna meglio di sessione) global.list.limit attraverso il metodo getUserState() e ritorna questo valore, a meno che un nuovo valore sia passato allo script tramite $_REQUEST['limit']. In questo caso è questo valore che viene salvato come nuova variabile di sessione (tramite setUserState()) ed è ritornato dalla funzione.

Se global.list.limit non esiste come variabile di sessione e nessun valore è passato in $_REQUEST['limit'], la funzione ritorna il valore di default che abbiamo passato come terzo argomento. In questo caso $mainframe->getCfg('list_limit') che non è nient'altro che il valore predefinito della lunghezza (cioè del numero delle righe per pagina) di tutte le tabelle dell'area di amministrazione, impostabile tramite Configurazione Globale -> Sito.

Quanto detto per $limit vale ovviamente per $limitstart.

Entrambi i valori sono salvati come stati di Model tramite il metodo setState() della classe JModel.

Implementiamo un metodo nuovo getTotal(). Questo metodo si limita a passare indietro il valore di ritorno del metodo privato _getListCount(), definito nella classe JModel, che riceve come argomento una query SQL (definita in _buildQuery()) e restituisce il numero totale dei record estratti dal database in base ad essa.

Inseriamo poi il metodo getPagination() che crea un'istanza della classe JPagination, la inizializza con i valori del numero totale dei record (ricavato da getTotal()), il numero della pagina da visualizzare (stato limitstart), il numero dei record da visualizzare su una pagina (stato limit) e restituisce l'oggetto. Vedremo poi come e da quale funzione sarà utilizzato.

Poiché i valori di limit e limitstart erano stati salvati nel costruttore come stati dell'oggetto Model tramite il metodo setState(), vengono ora recuperati con il reciproco getState().

Infine il metodo getData() dell'oggetto Model deve essere modificato per supportare la paginazione dei record. Il metodo privato _getList() (di JModel) deve ricevere oltre alla query sql (restituita da _buildQuery()) come già accadeva nelle precedenti versioni del componente, anche i valori di limit e limitstart senza i quali sarebbe sempre restituita la lista completa dei record estratti in base alla query senza alcuna paginazione.

View

Va poi modificata la classe MyFormViewMyForm. Il file è view.html.php in
.../administrator/components/com_myform/views/myform/

Come al solito le righe aggiunte sono in blu

class MyFormViewMyForm extends JView {
  function display($tpl = null) {
    $items =& $this->get('Data');
    $pagination = & $this->get('Pagination');
    $this->assignRef('items', $items);
    $this->assignRef('pagination', $pagination);
    parent::display($tpl);
  }
}

Veramente non c'è molto da dire. Ricordo solo che quando un oggetto Model contiene un metodo il cui nome inizia con get, l'oggetto View a cui detto oggetto Model è stato assegnato può accedere al valore di ritorno del metodo come se si trattasse di una sua proprietà il cui nome è uguale al nome del metodo meno il get iniziale.

Quindi

$pagination = & $this->get('Pagination');

assegna a $pagination l'oggetto creato dal metodo getPagination() che abbiamo implementato nell'oggetto Model poco fa.

Anche di assignref() si è già parlato negli articoli precedenti. Alla variabile $pagination viene assegnato un identificativo pagination che verrà utilizzato per riferirsi all'oggetto nel template.

Template

L'ultima modifica riguarda il template. Il file è default.php in
.../administrator/components/com_myform/views/tmpl/

defined('_JEXEC') or die('Restricted access');

$trh = '<thead><tr>
<th width="20%%">%s</th><th width="20%%">%s</th>
<th width="20%%">%s</th><th width="20%%">%s</th>
<th width="20%%">%s</th></tr></thead>';
$tr = '<tr>' . str_repeat('<td>%s</td>', 5) . '</tr>';
$html = '<form action="index.php" method="post" name="adminForm">
<table class="adminlist">';
$html .= '<tfoot><tr><td colspan="5">' . 
$this->pagination->getListFooter() .
'</td></tr></tfoot>';

$html .= sprintf($trh, JText::_('Nome'), JText::_('Cognome'), 
JText::_('Telefono'), JText::_('Indirizzo'), JText::_('Note'));
foreach($this->items as $item) {
  $html .= sprintf($tr, $item->nome, $item->cognome, $item->telefono, 
  $item->indirizzo, $item->note);
}
$html .= '</table>';
$html .= '<input type="hidden" name="option" value="com_myform" />
  <input type="hidden" name="task" value="" /></form>';
echo $html;

Viene inserito un form di nome adminForm e due campi nascosti option e task. Non è il caso di dilungarsi molto su questo (magari in futuro si potrà approfondire), è una parte standard che deve essere presente nell'interfaccia di amministrazione di ogni componente Joomla.

L'istruzione

$this->pagination->getListFooter()

visualizza nel footer della tabella gli elementi di interfaccia necessari alla navigazione (vedi foto)

Siamo nel template per cui $this->pagination è l'oggetto di classe JPagination creato nel metodo getPagination() dell'oggetto Model e a cui è stato assegnato l'identificativo pagination con assignRef() nell'oggetto View. Ripercorrete la strada all'indietro guardando il sorgente se qualcosa non è chiaro.

Siamo alla fine. Come al solito le spiegazioni a parole fanno sembrare tutto più difficile, ma a guardare bene per inserire la funzione di paginazione abbiamo dovuto scrivere non più di una ventina di righe di codice PHP.

La versione del componente aggiornata con tutte le modifiche apportate in quest'articolo è scaricabile dal sito, file myform4.zip

La prossima volta aggiungeremo le funzioni di modifica e cancellazione record.

Nessun commento:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.