Zend Framework, teoria di base (Controller)

Zend Framework Logo

Continuo a studiare e fare ordine nella mia testa.

I modi di instradare una richiesta (indirizzo web URI) verso il codice che svolgerà le funzioni necessarie a soddisfarla sono essenzialmente 2:

  • Page Controller
    Questa tecnica prevede l’uso di file separati, uno per ogni pagina (index.php, news.php, articoli.php, ecc.). Il controllo dell’applicazione risulta quindi decentralizzato in differenti files separati.
  • Front Controller
    Questo tipo di controller invece convoglia le richieste verso un unico file (solitamente index.php) che determina quale codice eseguire attraverso diversi sistemi.

Chi ha iniziato a programmare in PHP diversi anni fa non avrà difficoltà a ricordare quando tutto veniva smistato secondo la logica del Page controller. Zend Framework invece, come abbiamo già visto in precedenza, oltre al pattern MVC (Model View Controller), implementa anche il Front Controller pattern per rispondere alle richieste effettuate.

Il componente Zend_Controller è quello che si occupa di tutto ciò. E’ costituito dal Front Controller, dall’Action Controller e da altre classi di supporto.
Come abbiamo visto ogni richiesta effettuata al server web viene inoltrata ad un unico file (denominato “entrance point”, solitamente il nostro index.php) il quale avvia il Front Controller che ha il compito di identificare l’azione e il comando da eseguire in base all’URI richiesto. In Zend Framework questo controller è composto da due componenti essenziali: il router e il dispatcher. Il router determina quale azione deve essere chiamata e il dispatcher esegue la chiamata. Il tutto passa in mano all’Action Controller che si interfaccia a Model e View per costruire la risposta da fornire all’utente.

Vediamo ora nel dettaglio le varie fasi di avanzamento del Controller dello Zend Framework.

Request

E’ una qualsiasi richiesta HTTP che giunge al nostro web server. Viene incapsulata nella classe Zend_Controller_Request_Http che ne memorizza ogni dato (le nostre “vecchie” variabili $_GET, $_POST, $_COOKIE, $_SERVER e $_ENV). Zend Framework fornisce una serie di funzioni in grado di leggere e manipolare questi dati.

Router

La Request viene poi passata al Router che determina quale codice andrà eseguito. Il suo lavoro si basa essenzialmente sull’URI, che viene scomposto e interpretato, e giunge al termine quando vengono identificate le procedure da eseguire. Anche qui il Framework è farcito di una serie di classi che permettono di interagire direttamente con il router per poter arrivare anche a riscrivere parte del suo lavoro (Zend_Controller_Router_Rewrite).

Dispatch

Le procedure che andremo a creare per il nostro applicativo sono classi che estendono il componente Zend_Controller_Action. Ogni classe quindi identificherà un controller e i suoi metodi saranno le varie action da eseguire. Il Front Controller, una volta identificati controller e action, avvia il processo di dispatch che eseguirà le seguenti azioni:

  • caricare il controller (la classe definita da router)
  • istanziare la classe
  • invocare l’action (il metodo della classe definito da router)

Fatto ciò il dispatcher passerà il controllo dell’esecuzione alla classe dell’Action controller.

Action

Le Action sono tutte classi che dovranno essere derivate dalla principale Zend_Controller_Action. Ogni classe avrà a disposizione la Request (da cui leggere eventuali dati), la Response (per scriverli), le View (per la gestione delle viste dell’output) e i Model (per interfacciarsi al Database, ad esempio).
Una caratteristica fondamentale e molto utile delle Action è la possibilità di redirezionare tra loro le varie action (metodi delle classi) tra loro. In pratica possiamo far eseguire più di un action alla volta al nostro controller senza dover ricaricare la pagina.

Oltre alle singole azioni (metodi) che andremo a creare per ogni classe è possibile servirsi di alcuni metodi particolari che verranno eseguiti in momenti specifici: init() al momento in cui viene istanziata la classe, preDispatch() prima di eseguire il metodo, postDispatch() al termine delle operazioni svolte dal metodo. init() risulta particolarmente comodo nelle classi in cui decidiamo che potranno essere eseguite diverse action. In questo caso init() verrà eseguito una sola volta mentre il preDispatch() più volte, prima di ogni azione.

Una volta terminata l’esecuzione della/delle Action necessarie l’output che è stato generato viene inviato al client tramite il Response.

Response

Il Response è una sorta di contenitore nel quale andremo a caricare tutto l’output che invieremo all’utente. Se stiamo parlando di una risposta Web  l’oggetto del response sarà un’istanza del componente (classe) Zend_Controller_Response_Http.
Questo oggetto contiene tre tipi di dati:

  • Headers
    Non quello della pagina HTML bensì un header HTTP nel caso di una pagina Web
  • Body
    Nel caso di pagina web sarà appunto l’intero codice HTML che comporrà la pagina
  • Exception
    Per la gestione degli errori

E’ importante sottolineare che il response potrà essere di diverso tipo e non solo HTML (XML, PDF, ecc.). Il modello MVC infatti prevede che la logica sia separata dall’output (View) e questo, attraverso il response, potrà essere facilmente gestito.