giovedì 20 marzo 2008

Arriva la versione definitiva di Zend Framework 1.5

Maria Susana Diaz | 15:59 |
Zend Framework è un framework open source per lo sviluppo di applicazioni web, scritto in linguaggio PHP5 e rilasciato con licenza BSD.

Zend Framework - anche conosciuto ed identificato come ZF - è progettato con lo scopo di semplificare l'attività di sviluppo web ed agevolare la produttività mettendo a disposizione una serie di librerie e componenti a disposizione della community PHP.

Il momento è arrivato, la versione definitiva di Zend Framework 1.5 è arrivata e da qualche ora il link per scaricare la nuova release è ben visibile nella pagina dei download del sito.

Sito che, per l’occasione, è stato completamente rinnovato nella grafica sebbene la struttura interna sia rimasta quasi totalmente immutata.

Nuova homepage dunque ma soprattutto nuova versione di uno dei framework web in PHP 5 ad oggi più diffusi e apprezzati.

Abbiamo già avuto modo, nei giorni scorsi, di anticipare alcune delle novità principali di Zend Framework 1.5. Ecco un breve riepilogo:

  • Nuovo componente Zend_Form con supporto a script AJAX
  • Nuovi helper per le action e le view, per migliorare e semplificare l’interazione tra i vari componenti e con richieste AJAX
  • Nuovi adapter per la gestione delle autenticazioni, tra i quali Infocard, OpenId e LDAP
  • Supporto al formato degli indici di Lucene 2.1
  • Nuovo componente Zend_Layout per facilitare la creazione di layout per un progetto
  • Supporto della codifica UTF-8 per i documenti PDF
  • Nuovi client API per i web service Technorati, SlideShare e Nirvanix

Zend Framework 1.5 apporta sostanziali novità rispetto alle versioni precedenti e, in alcuni casi, qualche potenziale problema di retro compatibilità.
Per avvicinare nuovi utenti all’utilizzo è disponibile un breve tutorial, chiamato Zend Framework Quickstart, contenente una generale panoramica.

In realtà si tratta di un documento molto basilare che poco rende giustizia alle reali funzionalità di questo prodotto. E’ tuttavia un buon inizio, soprattutto per chi è ancora a digiuno.

fonte: framework.it

Home PageNota: questo documento è pensato per la versione 0.2 dello Zend Framework ed è molto difficile che possa funzionare con versioni successive oppure con l'ultima versione disponibile attraverso Subversion!
L'architettura Model View Controller (MVC)
Col passare del tempo una applicazione di questo tipo diventa ben presto non più gestibile e manutenibile. Con l'aumentare delle richieste di modifica da parte del cliente, il codice, stravolto in più punti, perde ogni leggibilità.

Un metodo per migliorare la manutenibilità del codice è dividere l'applicazione in 3 parti distinte, solitamente salvate in file separati:
Model
La parte dell'applicazione connessa con le caratteristiche dei dati da visualizzare. Nel codice precedente si riferisce al concetto di 'NEWS'. Qui di solito troviamo la business logic dell'applicazione e la parte che si occupa di leggere e scrivere sul db.
View
Tutto quello che serve per visualizzare i dati. Di solito si tratta prevalentemente di codice HTML.
Controller
Questa è la parte di logica che tiene insieme le due precedenti parti e che assicura che i corretti dati siano visualizzati sullo schermo.

Perchè parlare di MVC?

Perchè Zend Framework utilizza l'architettura Model-View-Controller (MVC) per dividere l'applicazione in sezioni più facili da sviluppare e da manutenere.
I requisiti

Zend Framework ha i seguenti requisiti:
• PHP 5.1.4 (or maggiore). No PHP 4.x.x
• Apache web server con il modulo mod_rewrite

Scaricare il Framework

Lo Zend Framework può essere scaricato all'indirizzo http://framework.zend.com/download in formato .zip o tar.gz. Al momento la versione corrente è la 0.2 ed è quella usata per l'applicazione descritta in questo documento.

Struttura delle directory

Mentre lo Zend Framework non prescrive alcuna particolare struttura di directory, il manuale consiglia uno standard. Questo implica che abbiate il pieno controllo sulla configurazione del vostro server Apache. Per semplificarci la vita, tuttavia, useremo una configurazione leggermente modificata, più semplice da realizzare.

Create una directory nella root del webserver chiamata zf-tutorial. In questo modo l'url per aprire l'applicazione che stiamo scrivendo sarà: http://localhost/zf-tutorial.
Create, poi, le seguenti directory all'interno della directory zf-tutorial, in modo da ottenere la seguente struttura:

zf-tutorial/ /application /controllers /models /views /library /public /images /scripts /styles

In pratica, abbiamo 3 directory separate, rispettivamente model, view e controller, tutte all'interno della directory application. I file di supporto statici come le immagini, gli script e i modelli CSS sono salvati in directory dedicate nella directory public. Tutto il Framework Zend, invece, va posizionato dentro la directory library. In questa directory, library, metteremo anche tutte le librerie che ci utilizzeremo per sviluppare l'applicazione.

Estraete, in pratica, il file scaricato ZendFramework-0.2.zip, in una directory temporanea. Prendete il contenuto di ZendFramework-0.2/library e copiatelo dentro zf-tutorial/library. A questo punto la directory zf-tutorial/library dovrebbe contenere una sottodirectory chiamata Zend e un file chiamato Zend.php.
Bootstrapping

Il controller del Framework Zend, Zend_Controller è disegnato per supportare siti web con url 'puliti'. In pratica tutte le richieste devono passare attraverso un unico index.php, chiamato bootstrapper (in italiano potrebbe essere 'lanciatore'?). Si tratta in pratica di un punto centrale per tutte le pagine del sito e assicura che l'ambiente dell'applicazione sia configurato in modo corretto per l'esecuzione. Per raggiungere il nostro scopo utilizziamoe un file .htaccess posizionato nella directory principale zf-tutorial:

FILE zf-tutorial/.htaccess:


RewriteEngine on RewriteRule .* index.php php_flag magic_quotes_gpc off php_flag register_globals off

Il comando redirect utilizzato è molto semplice e può essere interpretato nel seguente modo:
"qualsiasi url deve essere rediretto a index.php".

Già che ci siamo, settiamo un paio di parametri per PHP che ci fanno vivere un po' più tranquilli. Di solito dovrebbero già essere configurati nel file PHP.INI, però vogliamo essere veramente sicuri. Bisogna notare che php_flag funziona solo se utilizzate la versione mod_php. Se usate CGI/FastCGI, allora dovete proprio configurare i parametri nel file php.ini.

Tuttavia, questo redirect non è perfetto, in quanto tutte le richieste per le immagini, file javascript e file CSS non devono essere gestite da index.php. Ma visto che salviamo questi tipi di file in un'unica directory (public), basta aggiungere un altro file .htaccess nella directory zf-tutorial/public:

FILE zf-tutorial/public/.htaccess:

RewriteEngine off

Vogliamo, inoltre, proteggere le nostre directory che contengono l'applicazione e la libreria e quindi creiamo un altro paio di file .htaccess che bloccano gli accessi non autorizzati:

FILE zf-tutorial/application/.htaccess:

deny from all

FILE zf-tutorial/library/.htaccess:

deny from all

Nota: abbiamo usato diversi file .htaccess, ma questi per funzionare hanno bisogno che Apache sia configurato con la direttiva AllowOverride All nel file httpd.conf.

L'idea di utilizzare più file .htaccess è tratta dall'articolo “Blueprint for PHP Applications: Bootstrapping (Part 2) ” di Jayson Minard, dateci un occhio.
Il Bootstrap: index.php

zf-tutorial/index.php è il nostro file di bootstrap, e per iniziare scriviamo il seguente codice:

FILE zf-tutorial/index.php:

setRewriteBase($baseUrl); $controller = Zend_Controller_Front::getInstance(); $controller->setRouter($router); $controller->setControllerDirectory('./application/controllers'); // run! $controller->dispatch();


Visto che non abbiamo messo ?> alla fine del file. Questo è perchè non serve e non mettendolo è possibile individuare errori a volte difficili da trovare.

Scorriamo il file e cerchiamo di capirci qualcosa:

error_reporting(E_ALL|E_STRICT); date_default_timezone_set('Europe/Rome');

Queste linee ci assicurano che qualsiasi errore questo verrà mostrato a video (diamo per scontato che nel file php.ini la variabile display_errors sia posta a ON). E inoltre settiamo la nostra zona oraria come richiesto da PHP 5.

set_include_path('.' . PATH_SEPARATOR . './library/' . PATH_SEPARATOR . './application/models' . get_include_path()); include "Zend.php";

Il Framerwork Zend funziona solo se i suoi file sono nell'include path. Aggiungiamo, già che ci siamo, anche la directory che contiene i nostri model così li possiamo caricare facilmente in seguito.

Facciamo partire il tutto includendo il file Zend.php che ci da accesso alla classe Zend che contiene le funzioni statiche per caricare qualsiasi altra classe del framework.

Zend::loadClass('Zend_Controller_Front'); Zend::loadClass('Zend_Controller_RewriteRouter');

Il metodo Zend::loadClass carica la classe passata come parametro. Questo lo fa convertendo gli underscore (_) del parametro passato in separatori di path e aggiungendo .php alla fine. Perciò la classe Zend_Controller_Front sarà caricata dal file Zend/Controller/Front.php.
Se utilizzate questa stessa convenzione per chiamare le vostre librerie di classi potete utilizzare Zend::loadClass per caricarle.

Normalmente lo Zend Framework assume che il sito si trovi al livello di root del dominio, ovvero in http:/localhost/index.php.

Nel nostro caso invece stiamo lavorando in una sottodirectory chiamata /zf-tutorial, perciò dobbiamo utilizzare Zend_Controller_RewriteRouter. Per configurarlo, dobbiamo settare l'url di base al corretto URI del nostro file index.php. Ho usato $_SERVER[‘PHP_SELF’] per risparmiare tempo e in modo che funzioni in molte situazioni. Se questo non è il vostro caso, allora cambiate l'assegnamento a $baseUrl al corretto URI di index.php nel vostro sistema.

// setup controller $router = new Zend_Controller_RewriteRouter(); $baseUrl = substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], '/index.php')); $router->setRewriteBase($baseUrl); $controller = Zend_Controller_Front::getInstance(); $controller->setRouter($router); $controller->setControllerDirectory('./application/controllers');

A questo punto finalmente siamo arrivati al cuore della faccenda. Adesso abbiamo un'istanza del controller, tutto è stato configurato e possiamo eseguire la nostra applicazione:

// run! $controller-> dispatch();

Se aprite la pagina http://localhost/zf_tutorial/ dovreste vedere un Fatal Error simile al seguente:

Fatal error: Uncaught exception 'Zend_Exception' with message 'File
"./application/controllers\IndexController.php" was not found.
(etc.)

Ok, niente paura le cose funzionano correttamente, ma prima di proseguire dobbiamo prima capire che tipo di applicazione vogliamo mettere in piedi.
Il nostro Sito

Quello che vogliamo implementare è un semplice archivio per la nostra collezione di Album su CD. La pagina principale listerà tutti i CD e ci permetterà di aggiungere, modificare e cancellare gli Album. Tutti i dati saranno salvati in un database in una tabella come la seguente:
Campo Tipo NULL ? Note
id Integer No Primary key, Autoincrement
artist Varchar(100) No
title Varchar(100) No

Pagine del sito

Nel sito prevediamo che ci siano le seguenti pagine
Home Visualizzazione di tutti i CD e link a Modifica e Cancella. Inoltre un link a Nuovo Album.
Nuovo CD Pagina con form per aggiungere nuovi CD.
Modifica CD Pagina con form per modificare un CD
Cancella CD Questa pagina chiederà la conferma alla cancellazione e poi la eseguirà.

Organizzazione delle pagine

Prima di cominciare a scrivere codice è importante capire come il framework si aspetta che le pagine siano organizzate.
Ogni pagina dell'applicazione fa riferimento ad un'azione e le azioni sono raggruppate in controller. E questo si riflette nell'indirizzo URL della pagina.

Ad esempio per un indirizzo del tipo http://localhost/zftutorial/notizie/visualizza:

* l'applicazione è zftutorial,
* il controller è notizie
* l'azione è visualizza.

Questo sistema ci permette di raggruppare le azioni in un controller e di richiamarle una per volta. Ad esempio il controller notizie potrebbe contenere le azioni nuova, archiviate e visualizza.



Nel Framework Zend esiste poi un'azione speciale chiamata index. Questa azione è richiamata quando si invoca il controller senza specificare nessuna azione, come, ad esempio, nel seguente URL http://localhost/zftutorial/notizie/. In questo caso viene richiamata l'azione index del controller notizie.

Esiste anche un controller particolare, richiamato quando non viene specificato un controller nell'url. Questo controller, guarda caso, si chiama anche lui index. Quindi nell'url http://localhost/zftutorial/ viene richiamata l'azione index del controller index.

Scoperta la gestione delle pagine e degli url da parte di ZF allora possiamo comporre la seguente tabella che illustra dove dobbiamo andare a mettere il codice. Poichè abbiamo 4 pagine le possiamo raggruppare in un singolo controller come 4 azioni differenti:
Pagina Controller Azione
Home Index index
Nuovo CD Index add
Modifica CD Index edit
Cancella CD Index delete

Tutto qui, semplice, vero?
Implementiamo il controller

Adesso siamo pronti per scrivere il nostro controller. VEdiamo leconvezioni da adottare. In ZF un controller è una classe che deve essere chiamata {Controller name}Controller, ad esempio NotizieController. Notate che il nome deve iniziare con la lettera maiuscola. La classe deve poi essere salvata in un file chiamato {Controller name}Controller.php (es. NotizieController.php) all'interno della directory dei controller. Notate, di nuovo, che solo la prima lettera di {Controller name} deve essere maiuscola.

Le azioni invece sono delle funzioni pubbliche all'interno della classe controller e si devono chiamare {action name}Action. In questo caso le azioni devono iniziare con la lettera minuscola.

Nella nostra applicazione, il controller si chiamerà IndexController e sarà definito nel file zf-tutorial/application/controllers/IndexController.php:

FILE zf-tutorial/application/controllers/IndexController.php:

in IndexController::indexAction()"; } function addAction() { echo "

in IndexController::addAction()

"; } function editAction() { echo "

in IndexController::editAction()

"; } function deleteAction() { echo "

in IndexController::deleteAction()

"; } }

Così configurato, il controller stamperà il nome di ogni azione richiamata. Si può provare visitando i seguenti indirizzi:
Indirizzo Testo mostrato
http://localhost/zf_tutorial/ in IndexController::indexAction()
http://localhost/zf_tutorial/index/add in IndexController::addAction()
http://localhost/zf_tutorial/index/edit IndexController::editAction()
http://localhost/zf_tutorial/index/delete IndexController::deleteAction()

Abbiamo quindi un router che funziona in quanto le azioni corrette sono eseguite per ogni pagina della nostra applicazione. Se qualcosa non dovesse funzionare date un occhio alla sezione 'Problemi' alla fine del tutorial, magari trovate qualcosa che vi aiuta.

Adesso possiamo procedere con implementare la vista
Implementare la View

Il componente di Zend Framework che si occupa di gestire le View si chiama, senza sorprese, Zend_View. Lo scopo di questo componente, secondo l'architettura MVC, è quello di separare il codice che visualizza la pagina dal codice che esegue le azioni.

Il modo di usare Zend_View è il seguente:

$view = new Zend_View(); $view->setScriptPath('/path/ai/file/da/visualizzare'); echo $view->render('view.php');

Si nota subito che se mettiamo queste 3 righe direttamente in ogni azione del controller ci troviamo a ripetere il codice di inizializzazione della classe. Codice che poco 'ci azzecca' con il controller. Ci conviene allora effettuare questa inizializzazione all'inizio, in un altro punto e poi utilizzare un oggetto già inizializzato all'interno del controller. (meno codice si scrive più facile è mantenere l'applicazione e meno errori si fanno).

Questo problema di inizializzazione è stato previsto dagli sviluppatori di ZF ed è previsto un registry (niente a che vedere con quello di Windows) dove salvare e recuperare gli oggetti durante l'esecuzione.

Il codice per registrare un oggetto è:

Zend::register('obj', $object);

e per recuperarlo è:

$object = Zend::registry('obj');

Possiamo quindi integrare le view nelle nostre applicazioni inizializzando l'oggetto View e salvandolo nel registry nel nostro file di bootstrap (zf-tutorial/index.php):


FILE zf-tutorial/index.php:

... Zend::loadClass('Zend_Controller_Front'); Zend::loadClass('Zend_Controller_RewriteRouter'); Zend::loadClass('Zend_View'); // register the view we are going to use $view = new Zend_View(); $view->setScriptPath('./application/views'); Zend::register('view', $view); // setup controller $route = new Zend_Controller_RewriteRouter(); $controller = Zend_Controller_Front::getInstance(); ...

I cambiamenti che abbiamo fatto al file sono in grassetto e dovrebbero essere abbastanza chiari. Notate che prima di istanziare una classe occorre prima caricarla dal file utilizzando Zend::LoadClass().
Dopo aver registrato l'oggetto View nel registry lo possiamo recuperare ed utilizzare nelle azioni del Controller.

Cambiamo quindi l'IndexController come segue:

FILE zf-tutorial/application/controllers/IndexController.php:

title = "My Albums"; echo $view->render('indexIndex.tpl.php'); } function addAction() { $view = Zend::registry('view'); $view->title = "Add New Album"; echo $view->render('indexAdd.tpl.php'); } function editAction() { $view = Zend::registry('view'); $view->title = "Edit Album"; echo $view->render('indexEdit.tpl.php'); } function deleteAction() { $view = Zend::registry('view'); $view->title = "Delete Album"; echo $view->render('indexDelete.tpl.php'); } }

In pratica, in ogni funzione, non facciamo altro che recuperare l'oggetto view salvato nel registry e assegnargli una variabile title. Richiamiamo, poi, la visualizzazione. Come risulta ovvio, a questo punto abbiamo bisogno di 4 file per la visualizzazione della nostra applicazione. Questi file, denominati template, seguono la seguente convenzione per il nome. Ogni file si chiama come il controller + l'azione a cui fa riferimento, seguito da .tpl.php in modo che risulti immediatamente chiaro che si tratta di una template e quale azione del controller la richiama.

php echo $this->escape($this->title); ?>FILE zf-tutorial/application/views/indexIndex.tpl.php:

escape($this->title); ?>


?php echo $this->escape($this->title); ?>FILE zf-tutorial/application/views/indexAdd.tpl.php:
escape($this->title); ?>

FILE zf-tutorial/application/views/indexEdit.tpl.php:
escape($this->title); ?>
escape($this->title); ?>
FILE zf-tutorial/application/views/indexDelete.tpl.php:
escape($this->title); ?>
escape($this->title); ?>
Se adesso richiamiamo ogni controller/azione dovremmo vedere i titoli in grassetto.

Codice HTML ripetuto

Salto subito all'occhio che c'è un sacco di codice in comune nelle nostre template. Possiamo allora raccogliere tutto il codice uguale, richiamato dalle azioni, in un unico file chiamato site.tpl.php. Lo possiamo usare per fornici la sezione esterna della nostra pagina e rendere poi il file che fornisce la parte specifica di ogni azione.

Dobbiamo perciò cambiare ancora il nostro controller, nel seguente modo:

FILE zf-tutorial/application/controllers/IndexController.php:

title = "My Albums"; $view->actionTemplate = 'indexIndex.tpl.php'; echo $view->render('site.tpl.php'); } function addAction() { $view = Zend::registry('view'); $view->title = "Add New Album"; $view->actionTemplate = 'indexAdd.tpl.php'; echo $view->render('site.tpl.php'); } function editAction() { $view = Zend::registry('view'); $view->title = "Edit Album"; $view->actionTemplate = 'indexEdit.tpl.php'; echo $view->render('site.tpl.php'); } function deleteAction() { $view = Zend::registry('view'); $view->title = "Delete Album"; $view->actionTemplate = 'indexDelete.tpl.php'; echo $view->render('site.tpl.php'); } }

Abbiamo, cioè, introdotto una nuova variabile chiamata actionTemplate e poi rendiamo lo stesso file chiamato site.tpl.php in tutti i casi.

I file view diventano così:

FILE zf-tutorial/application/views/site.tpl.php:

escape($this->title); ?>
render($this->actionTemplate); ?>


FILE zf-tutorial/application/views/indexIndex.tpl.php:
escape($this->title); ?>

zf-tutorial/application/views/indexAdd.tpl.php
escape($this->title); ?>

zf-tutorial/application/views/indexEdit.tpl.php
escape($this->title); ?>

zf-tutorial/application/views/indexDelete.tpl.php
escape($this->title); ?>

Mancanza di Stile

Anche se questo è una breve guida, abbiamo comunque bisogno di un foglio di stile CSS per far apparire la nostra applicazione un pò più presentabile!

FILE zf-tutorial/application/views/site.tpl.php

escape($this->title); ?>... ...

FILE zf-tutorial/public/styles/site.css:

body,html { font-size:100%; margin: 0; font-family: Verdana,Arial,Helvetica,sans-serif; color: #000; background-color: #fff; } h1 { font-size:1.4em; color: #000080; background-color: transparent; } #content { width: 770px; margin: 0 auto; } label { width: 100px; display: block; float: left; } #formbutton { margin-left: 100px; }

Il database

Adesso che abbiamo separato il controllo dell'applicazione dalla visualizzazione, è arrivato il momento di dedicarci al model della nostra applicazione. Ricordate che il model è il cuore dell'applicazione che si occupa delle business rules, e perciò, nel nostro caso, si rapporta con il database.
Utilizzeremo, qui, la classe del ZF chiamata Zend_Db_Table che si occupa di inserire, aggiornare e cancellare righe dalle tabelle del database.
Configurazione

Per usare Zend_Db_Table, dobbiamo specificare quale database utilizzare insieme ad username e password.
Poichè non ci piace includere queste informazioni nel codice, utilizziamo un file di configurazione per conservare queste informazioni.

Per fortuna lo ZF fornisce un oggetto flessibile che ci permette di accedere ai file di configurazione. Al momento il file di configurazione può essere un array PHP, un file di tipo INI oppure di tipo XML. Nel nostro esempio utilizzeremo un file INI:

FILE zf-tutorial/application/config.ini:

[general] db.adapter = PDO_MYSQL db.config.host = localhost db.config.username = rob db.config.password = 123456 db.config.dbname = zftest

Naturalmente dovrete usare il vostro username e password e non il mio!
Utilizzare Zend_Config è veramente facile:

$config = new Zend_Config_Ini('config.ini', 'section');

Notate che in questo caso, Zend_Config_Ini carica solo 1 sezione dal file INI file, e non tutte le sezione. La sintassi supporta, nel parametro section name , la possibilità di caricare ulteriori sezioni.

Zend_Config inolte tratta il 'punto' nel parametro come un separatore gerarchico che permette di raggruppare parametri di configurazione correlati. Ad esempio nel nostro config.ini , host, username, password e nome db sono raggruppati sotto $config->db->config.
Caricheremo la configurazione nel nostro bootstrap (index.php).

FILE zf-tutorial/index.php:

... Zend::loadClass('Zend_Controller_Front'); Zend::loadClass('Zend_Controller_RewriteRouter'); Zend::loadClass('Zend_View'); Zend::loadClass('Zend_Config_Ini'); // load configuration $config = new Zend_Config_Ini('./application/config.ini', 'general'); Zend::register('config', $config); // register the view we are going to use $view = new Zend_View(); $view->setScriptPath('./application/views'); ...


I cambiamenti sono in grassetto. In pratica carichiamo la classe che utilizziamo (Zend_Config_Ini) e carichiamo la sezione 'general' del nostro file di configurazione (application/config.ini) nell'oggetto $config.

Nota: in questo esempio non abbiamo bisogno di salvare l'oggetto $config nel registry, ma è buona pratica nelle applicazioni reali di farlo, soprattutto se si hanno più configurazioni di database nel file INI.
Configurazione di Zend_Db_Table

Per utilizzare Zend_Db_Table occorre comunicargli le informazioni sulla configurazione del db che abbiamo appena letto. Per questo dobbiamo creare un'istanza di Zend_Db e registrare questa con la funzione statica Zend_Db_Table:: setDefaultAdapter(). Naturalmente facciamo questo nel bootstrap (aggiunte in grassetto):

FILE zf-tutorial/index.php:

... Zend::loadClass('Zend_Config_Ini'); Zend::loadClass('Zend_Db'); Zend::loadClass('Zend_Db_Table'); // load configuration $config = new Zend_Config_Ini('./application/config.ini', 'general')); Zend::register('config', $config); // setup database $db = Zend_Db::factory($config->db->adapter, $config->db->config->asArray()); Zend_Db_Table::setDefaultAdapter($db); // register the view we are going to use $view = new Zend_View(); $view->setScriptPath('./application/views'); Zend::register('view', $view); ...

Creazione della tabella

Utilizzeremo MySql e l'istruzione SQL per creare il database è la seguente:

CREATE TABLE album ( id int(11) NOT NULL auto_increment, artist varchar(100) NOT NULL, title varchar(100) NOT NULL, PRIMARY KEY (id) )

Potete eseguire questo comando in un cliente MySql come phpMyAdmin
Inserimento di record di prova

Inseriremo anche un paio di record nella tabella in modo da testare le funzionalità della pagina home.

possiamo quindi utilizzare il seguente comando SQL:

INSERT INTO album (artist, title) VALUES ('Begin To Hope', 'Regina Spektor'), ('Pendulum', 'Creedence Clearwater Revival');


Il Model

Zend_Db_Table è una classe astratta, perciò dobbiamo derivare la nostra classe specifica per trattare i CD. Per default, Zend_Db_Table si aspetta che il nome della classe sia uguale al nome della tabella. Perciò la nostra classe si chiamerà Album in quanto la tabella si chiama album (Nota del traduttore: questa cosa non mi piace in quanto solitamente le tabelle hanno nomi plurali e in questo modo si obbliga ad utilizzare nomi singolari. Ruby on rails ha ben altra implementazione che tiene conto di questo).

Inoltre Zend_Db_Table assume che la tabella abbia una chiave primaria ,autoincrementante, chiamata id. Entrambe queste convenzioni possono essere modificate.

Salviamo quindi la nostra tabella Album nella directory model:

FILE zf-tutorial/application/models/Album.php:

title = "My Albums"; $album = new Album(); $view->albums = $album->fetchAll(); $view->actionTemplate = 'indexIndex.tpl.php'; echo $view->render('site.tpl.php'); } ...


La funzione Zend_Db_Table::fetchAll() restituisce un oggetto Zend_Db_Table_Rowset che ci permette di iterare sulle righe restituite nel file template:

FILE zf-tutorial/application/views/indexIndex.tpl.php:

escape($this->title); ?>

Add new album

albums as $album) : ?>
Title Artist
escape($album->title);?> escape($album->artist);?> id;?>" >Edit id;?>" >Delete


Se visitiamo http://localhost/zf-tutorial/ dovremmo vedere una lista di tutti (due) i nostri album.
Gestire variabili GET e POST

In una classica applicazione PHP, le variabili globali $_POST e $_GET sono utilizzate per trovare i parametri inseriti dall'utente. Il problema è che molte volte ci dimentichiamo di controllare che i dati forniti per un certo campo siano del tipo previsto. Se non effettuiamo questo tipo di validazione dei dati è possibile incorrere in problemi di sicurezza del software o, nel migliore dei casi, avere un'applicazione che non funziona. Lo ZF ci mette a disposizione la classe Zend_Filter_Input per effettuare la validazione dei dati forniti dall'utente

Per usare Zend_Filter_Input:

$postArray = new Zend_Filter_Input($_POST); $username = $postArray->testName('username'); if ($username !== false) { // $username is a valid name }

Una cosa importante da ricordare è che Zend_Filter_Input cancella l'array di input. Nel senso che, dopo aver creato un oggetto Zend_Filter_Input per $_POST, $_POST è cancellato. Per questo, utilizzeremo i filtri nell'index e salvermeo i risultati nel registry in modo da accedere ai dati ogni volta che ci servono.

FILE zf-tutorial/index.php:

... Zend::loadClass('Zend_Db'); Zend::loadClass('Zend_Db_Table'); Zend::loadClass('Zend_Filter_Input'); // register the input filters Zend::register('post', new Zend_Filter_Input($_POST)); Zend::register('get', new Zend_Filter_Input($_GET)); // load configuration ...

Adesso possiamo recuperare una variabile POST con il seguente codice:

$post = Zend::registry('post'); $myVar = $post->testAlpha('myVar');

Aggiungere nuovi CD

Adesso che abbiamo impostato un filtro per le variabili POst, possiamo implementare la funzioanlità di creazione dei nuovi Album.

Ci sono 2 parti in questa funzionalità:

* Visualizzazione di un modulo dove l'utente può inserire i dettagli
* Processamento del modulo e inserimento dei data nel database.



Tutto questo è fatto nell'azione addAction():

FILE zf-tutorial/application/controllers/IndexController.php:

... function addAction() { $view = Zend::registry('view'); $view->title = "Add New Album"; if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { $post = Zend::registry('post'); $artist = trim($post->noTags('artist')); $title = trim($post->noTags('title')); if ($artist != '' && $title != '') { $data = array( 'artist' => $artist, 'title' => $title ); $album = new Album(); $album->insert($data); $url = '/zf-tutorial/'; $this->_redirect($url); return; } } // set up an "empty" album $view->album = new stdClass(); $view->album->id = ''; $view->album->artist = ''; $view->album->title = ''; // additional view fields required by form $view->action = 'add'; $view->buttonText = 'Add'; $view->actionTemplate = 'indexAdd.tpl.php'; echo $view->render('site.tpl.php'); } ...


Notate come controlliamo la variabile $_SERVER['REQUEST_METHOD'] per capire se la form è stata inviata dall'utente. Nel caso, troviamo i dati sull'artista e sul titolo dall'array di post utilizzando la funzione noTags() per assicurarci che non sia stato introdotto HTML e poi utilizziamo la nostra classe Album() per inserire le informazioni in una nuova riga della tabella.

Infine prepariamo la view per la form che abbiamo nella template. Considerando bene, la form utilizzata nell'azione di modifica sarà molto simile alla form utilizzata nel nuovo inserimento e quindi utilizzeremo in entrambe i casi un solo file richiamata sia da indexAdd.tpl.php che da indexEdit.tpl.php:

I template per aggiunere un album quindi sono:

FILE zf-tutorial/application/views/indexAdd.tpl.php;
escape($this->title); ?>
render('_indexForm.tpl.php'); ?>

zf-tutorial/application/views/_indexForm.tpl.php

action; ?>" method="post">
escape(trim($this->album->artist));?>"/>
escape($this->album->title);?>"/>
album->id; ?>" /> escape($this->buttonText); ?>" />
Si tratta di un codice abbastanza semplice. Poichè intendiamo utilizzare _indexForm.tpl.php anche per l'azione di modifica, abbiamo utilizzato una variabile per indicare l'azione ($this->action). Nello stesso modo, utilizziamo una variabile per il testo da mostrare sul bottone di Invio.
Modifica di un CD

Modificare un album è quasi uguale che aggiungerne uno nuovo, perciò il codice è simile:

FILE zf-tutorial/application/controllers/IndexController.php:

... function editAction() { $view = Zend::registry('view'); $view->title = "Edit Album"; $album = new Album(); if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { $post = Zend::registry('post'); $id = $post->testInt('id'); $artist = trim($post->noTags('artist')); $title = trim($post->noTags('title')); if ($id !== false) { if ($artist != '' && $title != '') { $data = array( 'artist' => $artist, 'title' => $title, ); $where = 'id = ' . $id; $album->update($data, $where); $url = '/zf-tutorial/'; $this->_redirect($url); return; } else { $view->album = $album->find($id); } } } else { // album id should be $params['id] $params = $this->_action->getParams(); $id = 0; if (isset($params['id'])) { $id = (int)$params['id']; } if ($id > 0) { $view->album = $album->find($id); } } // additional view fields required by form $view->action = 'edit'; $view->buttonText = 'Update'; $view->actionTemplate = 'indexEdit.tpl.php'; echo $view->render('site.tpl.php'); } ...

Notare che recuperiamo il parametro 'id' dall'array $params quando non siamo in modo "post", poichè questo è il modo in cui abbiamo settato le cose nel file index.php.

Il template è il seguente:

FILE zf-tutorial/application/views/indexEdit.tpl.php;

render('_indexForm.tpl.php'); ?>
escape($this->title); ?>
Refactor!

Non vi sarà certo sfuggito che AddAction() e EditAction() sono molto simili e che quindi le template di inserimento e modifica sono identiche. A questo punto è necessario un minimo di refactoring! E questo è un esercizio per te, caro lettore...
Cancellare un Album

Per completare la nostra applicazione, dobbiamo aggiungere la cancellazione. Abbiamo già un link per la cancellazione accanto ad ogni CD nella nostra lista e l'approccio naif è quello di cancellare il CD quando il link è cliccato. Niente di più sbagliato. Ricordate le specifiche HTTP! non vi ricordate che non dobbiamo mai fare un'azione irreversibile in seguito ad un GET, ma solo dopo un POST? Google Accelerator lo ha dimostrato molto bene a un sacco di persone.

Dobbiamo, quindi, mostrare un modulo di conferma dopo che l'utente clicca Cancella e, se clicca Si, effettuare la cancellazione.

Il codice, quindi, sembra in qualche modo quello delle azioni Aggiungi e Modifica:

FILE zf-tutorial/application/controllers/IndexController.php:

... function deleteAction() { $view = Zend::registry('view'); $view->title = "Delete Album"; $album = new Album(); if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { $post = Zend::registry('post'); $id = $post->getInt('id'); if (strtolower($post->testAlpha('del')) == 'yes' && $id > 0) { $where = 'id = ' . $id; $album->delete($where); } } else { // album id should be $params['id] $params = $this->_action->getParams(); if (isset($params['id'])) { $id = (int)$params['id']; if ($id > 0) { $view->album = $album->find($id); $view->actionTemplate = 'indexDelete.tpl.php'; // only render if we have an id. echo $view->render('site.tpl.php'); return; } } } // redirect back to the album list in all cases unless we are // rendering the template $url = '/zf-tutorial/'; $this->_redirect($url); } ...

Ancora una volta, utilizziamo il trucco di controllare il metodo di richiesta per capire se dobbiamo mostrare il modulo di conferma oppure eseguire la cancellazione. Cancellazione che viene eseguita utilizzando la classe Album(). In particolare chiamando Zend_Db_Table::delete().
Notate che ritorniamo immediatamente dopo aver chiamato la funzione render(). Questo per ridirigersi alla lista degli Album alla fine della funzione. Perciò se qualcuna delle funzioni di controllo fallisce, possiamo tornare alla lista degli album senza dover chiamare _redirect() più volte all'interno della funzione.

La template è una semplice form:

FILE zf-tutorial/application/views/indexDelete.tpl.php:
escape($this->title); ?>
album) :?>

Are you sure that you want to delete 'escape($this->album->title); ?>' by 'escape($this->album->artist); ?>'?

album->id; ?>" />

Cannot find album.

Problemi?

Se avete problemi a far funzionare qualsiasi azione che non sia index/index , allora la causa più comune è che il router non riesce a determinare la directory dove si trova il vostro sitoweb.
Dalle mie investigazioni, questo di solito succede, quando l'URL al sito web è diverso dalla directory a partire dalla radice del web.

Nell'esempio, in index.php, abbiamo provato a risolvere la cosa con $_SERVER[‘PHP_SELF’]. Se questo non funziona allora occorre impostare un valore per $baseURL manualmente.

FILE zf-tutorial/index.php:

... // setup controller $router = new Zend_Controller_RewriteRouter(); $baseUrl = '/mysubdir/zf-tutorial'; $router->setRewriteBase($baseUrl); $controller = Zend_Controller_Front::getInstance(); $controller->setRouter($router); ...

Occorre sostituire '/mysubdir/zf-tutorial/' con il corretto URL verso index.php. Adesempio, se l'URL per index.php è s http://localhost/~ralle/zf_tutorial/index.php
allora l'argomento corretto per setRewriteBase() è '/~ralle/zf_tutorial/'.



TiPI (Ti Potrebbe Interessare)
LinuxLinks

Trovato questo articolo interessante? Condividilo sulla tua rete di contatti in Twitter, sulla tua bacheca su Facebook, in Linkedin, Instagram o Pinterest. Diffondere contenuti che trovi rilevanti aiuta questo blog a crescere. Grazie!

LINKEDIN