Zend Framework è un progetto open source costruito intorno ad una forte community di oltre 400 sviluppatori e sponsorizzato da grandi corporation tra cui Microsoft, Fox Interactive Media, IBM e Google. Esso è conosciuto e largamente impiegato dagli sviluppatori nella creazione facile e veloce di applicazioni PHP di nuova generazione.
Zend Framework è oggi arrivato alla versione 1.5 totalizzando dal suo debutto più di quattro milioni di download.
L\'obiettivo del workshop è quello di introdurre gli utenti all\'utilizzo di Zend Framework mostrando i benefici in termini di produttività, flessibilità e sicurezza in ogni ambito dello sviluppo mediante la realizzazione di una vera applicazione PHP.
2. L'applicazione
|
| 31
Zend Framework dalla A alla Zend
mar 2008
2
3. Divide et Impera
• E' sempre conveniente separare il livello che incapsula
la business logic da quello di presentazione
• Per questo è importante dividere il codice HTML da
quello PHP.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
3
4. Ottenere la separazione
• Ci sono molti modi per dividere la logica dai template.
• Sicuramente la maniera più veloce (ma non la più
conveniente) è quella di includere le pagine HTML
all'interno dei nostri script PHP.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
4
5. Esempio di separazione
index.php index.tpl
$content = array(); <html>
$content['title']='Titolo'; [...]
$content['text']='Testo'; <body>
<div id=”title”>
include_once('index.tpl'); <?php echo $content['title'] ?>
</div>
<div id=”text”>
<?php echo $content['text'] ?>
</div>
</body>
</html>
|
| 31
Zend Framework dalla A alla Zend
mar 2008
5
6. Design Pattern?
• Non è facile trovare il modo perfetto per scrivere
un'applicazione.
• I design pattern sicuramente ci vengono in aiuto per
identificare i nostri bisogni e costruire applicazioni solide
e manutenibili.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
6
7. Il Pattern MVC
• Il design pattern MVC implementa la concezione di
Divide et Impera dividendo l'applicazione addirittura in
tre blocchi distinti:
• Model
• View
• Controller
|
| 31
Zend Framework dalla A alla Zend
mar 2008
7
8. Controller
• I controller si occupano di analizzare le richieste
dell'utente per inviarlo alla pagina desiderata.
• Mappano i cambiamenti della User Interface
(normalmente attraverso una vista) verso i modelli.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
8
10. View
• Visualizzano la User Interface
• Richiedono dati ai Modelli (attraverso i controller)
• Inviano eventi e richieste ai controller
|
| 31
Zend Framework dalla A alla Zend
mar 2008
10
11. Flusso della nostra applicazione
BOOTSTRAP index.php
Tutte le richieste vengono inviate a
un file di bootstrap che istanzia un oggetto
Front Controller
Lista dei post front controller per elaborare le richieste.
l'utente richiede la visualizzazione Il Front Controller istanzia il controller che si
dei post occupa della gestione dei post e chiama
l'azione di visualizzazione
class Post Controller: Post
PostController
extends Zend_Controller_Action
Model: Post
Action: List listAction()
I dati elaborati dal modello vengono inviati
alla vista per la creazione dell'html finale
Viene istanziato un oggetto del
modello che si occupa di estrarre i
View: List list.pthml
post dal db. I risultati vengono L'html viene creato e visualizzato
restituiti dal modello al controller all'utente
|
| 31
Zend Framework dalla A alla Zend
mar 2008
11
12. Il formato della richiesta
• Nell'esempio precedente l'utente richiedeva la lista dei
post.
• La richiesta per essere interpretata dal front controller di
Zend Framework deve essere composta in questo
modo:
http:// server / controller / action
http:// localhost / post / list
|
| 31
Zend Framework dalla A alla Zend
mar 2008
12
13. Creiamo la struttura dell'applicazione
• Creare la struttura per un progetto con Zend
Framework è più facile di quanto immaginiamo
utilizzando Zend Studio for Eclipse.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
13
14. Capire la struttura MVC
• application
• default
• controllers
• models
• views
• scripts
• html
• index.php
• .htaccess
• images / scripts / styles
|
| 31
Zend Framework dalla A alla Zend
mar 2008
14
15. Il file .htaccess
●
Per fare in modo che il Front Controller all'interno del
bootstrap (index.php) riceva tutte le richieste degli
utenti dobbiamo utilizzare il modulo mod_rewrite di
Apache.
●
Normalmente la nostra richiesta di esempio:
●
http://localhost/post/list
●
Genererebbe un errore 404 di pagina non trovata
perchè post e list non sono cartelle presenti
fisicamente nella DocumentRoot del nostro server web.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
15
16. Analizziamo il file .htaccess
RewriteEngine on
RewriteRule !.(js|ico|gif|jpg|png|css)$ index.php
●
Con questa semplice espressione regolare indirizziamo
tutte le richieste verso index.php escludendo le risorse
statiche.
●
Le risorse statiche (immagini, fogli di stile, file
javascript...) non devono essere elaborate dal Front
Controller e per questo vengono escluse identificandole
attraverso l'estensione.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
16
17. Il Bootstrap
●
Zend Studio for Eclipse ha creato per noi anche il file
index.php che prima abbiamo chiamato bootstrap.
require_once 'Zend/Controller/Front.php';
set_include_path(....)
$controller = Zend_Controller_Front::getInstance();
$controller>
setControllerDirectory('../application/default/controllers');
$controller>throwExceptions(false); // should be turned on in
development time
// run!
$controller>dispatch();
|
| 31
Zend Framework dalla A alla Zend
mar 2008
17
18. I controller
●
Come già detto in precedenza tutti i controller sono
classi derivate da Zend_Controller_Action.
●
Tutti i controller devo essere chiamati
[Nome]Controller con la prima lettera del nome
maiuscola poi tutto CamelCase.
●
Devono essere salvati nel file [Nome]Controller.php
all'interno della cartella dei controller che abbiamo
specificato nel bootstrap.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
18
19. Perchè IndexController e indexAction
●
Se nella richiesta l'utente non specifica nè un controller
nè un'azione il front controller chiamerà
automaticamente IndexController>indexAction.
●
Se viene specificato un controller ma non un'azione
verrà chiamata l'azione indexAction del controller
specificato.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
19
20. IndexController
class IndexController extends Zend_Controller_Action
{
/**
* The default action show the home page
*/
public function indexAction()
{
// TODO Autogenerated IndexController::indexAction()
//action
}
}
●
Tutte le azioni sono metodi della classe chiamate come
[nome]Action() con la prima lettera minuscola e poi
tutto CamelCase.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
20
21. Il ViewRender
●
Il ViewRenderer è un helper che automaticamente
visualizzerà la vista corrispondente all'azione chiamata.
●
Ad esempio, se l'azione chiamata è la indexAction() di
IndexController, il ViewRenderer visualizza
automaticamente la vista index.pthml che si trova in
application/views/scripts/index
●
Generalizzando:
●
[nomeAzione].phtml
●
../application/views/scripts/[NomeController]
|
| 31
Zend Framework dalla A alla Zend
mar 2008
21
22. index.pthml
<!DOCTYPE html PUBLIC quot;//W3C//DTD XHTML 1.0 Transitional//ENquot;
quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtdquot;>
<html xmlns=quot;http://www.w3.org/1999/xhtmlquot;>
<head>
<meta httpequiv=quot;ContentTypequot; content=quot;text/html; charset=UTF8quot; />
<title>New Zend Framework Project</title>
</head>
<body>
Hello, world!
</body>
</html>
|
| 31
Zend Framework dalla A alla Zend
mar 2008
22
24. Zend_Layout
●
Zend_Layout è il modulo di Zend Framework che ci
permette di realizzare il classico two step view.
●
Il layout dell'applicazione viene seperato dalle view
permettendoci di inserire il contenuto delle nostre viste
all'interno di un'altra vista che normalmente rappresenta
il template del sito.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
24
25. Configuriamo Zend_Layout
●
Prima di iniziare ad utilizzarlo dobbiamo configurare
l'istanza di Zend_Layout nel bootstrap.
/**
* Setup Layout
*/
$options = array(
'layout' => 'main',
'layoutPath' => '../application/default/views/layouts',
'contentKey' => 'content'
);
Zend_Layout::startMvc($options);
|
| 31
Zend Framework dalla A alla Zend
mar 2008
25
26. Creiamo il layout
<!DOCTYPE html PUBLIC quot;//W3C//DTD XHTML 1.0 Strict//ENquot;
quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1strict.dtdquot;>
<html xmlns=quot;http://www.w3.org/1999/xhtmlquot;>
<head>
<meta httpequiv=quot;ContentTypequot; content=quot;text/html; charset=UTF8quot; />
<title>Zend Framework Blog</title>
<link rel=quot;stylesheetquot; href=quot;/styles/main.cssquot; />
</head>
<body>
<div id=quot;structurequot;>
<div id=quot;contentquot;>
<?php echo $this>layout()>content; ?>
</div>
</div>
</body>
</html>
|
| 31
Zend Framework dalla A alla Zend
mar 2008
26
27. Il Placeholder “content”
<php echo $this>layout()>content ?>
●
Content è il placeholder che abbiamo specificato nella
configurazione come contentKey.
●
All'interno di questo placeholder verrà automaticamente
inserito il contenuto della vista associata all'azione
chiamata.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
27
29. Zend_Db
●
Zend_Db è un layer di accesso al database leggero e
potente che fornisce un'interfaccia a PDO e ad altre
estensioni per i db.
Adapter estendibili per ogni driver di database.
Un profiler delle query
Un API per la costruzione delle istruzioni di SELECT.
Un supporto robusto per prepared statements e quoting
|
| 31
Zend Framework dalla A alla Zend
mar 2008
29
30. Configuriamo Zend_Db
●
Prima di poter utilizzare Zend_Db dobbiamo
configurarlo nel bootstrap.
●
Le impostazioni di configurazione verranno recuperate
da un file .ini utilizando Zend_Config.
●
Il file di configurazione da utilizzare è come questo:
[development]
adapter = PDO_MYSQL
host = localhost
username = root
password =
dbname = blog
|
| 31
Zend Framework dalla A alla Zend
mar 2008
30
31. Leggiamo la configurazione
● $config = new
Zend_Config_Ini('../application/conf/db.ini','development');
●
Con la riga precedente parsiamo il file di configurazione
e creiamo un oggetto di Zend_Config_Ini.
●
Le informazioni adesso saranno disponibili direttamente
come proprietà dell'oggetto $config o utilizzando il
metodo toArray() che crea un array a partire dalla
configurazione.
●
Ad esempio $config>adapter
|
| 31
Zend Framework dalla A alla Zend
mar 2008
31
32. Creiamo un oggetto Zend_Db
● $db = Zend_Db::factory($config>adapter,$config>toArray());
●
Per creare un istanza di Zend_Db utilizziamo il suo
metodo factory passando come primo parametro
l'adapter che abbiamo letto dalla configurazione e come
secondo un array con i parametri di connessione.
●
L'array deve essere associativo e contenere le chiavi:
●
host
●
username
●
password
●
dbname
|
| 31
Zend Framework dalla A alla Zend
mar 2008
32
34. Zend_Db_Table
●
Zend_Db_Table è una soluzione potente ed efficace
per la programmazione ad oggetti con i database.
• Implementa i pattern Table Data Gateway e Row Data
Gateway.
• Legge i metadati dal database senza la necessità di complessi
file di configurazione.
• Fornisce un meccanismo per interrogare tabelle collegate
|
| 31
Zend Framework dalla A alla Zend
mar 2008
34
35. Configuriamo Zend_Db_Table
●
L'unica configurazione da fare a Zend_Db_Table è
quella di settare l'oggetto Zend_Db che abbiamo
appena creato come default adapter.
Zend_Db_Table::setDefaultAdapter($db);
|
| 31
Zend Framework dalla A alla Zend
mar 2008
35
36. Creiamo i modelli necessari
●
Tutte le classi che implementano Zend_Db_Table
devono essere figlie di Zend_Db_Table_Abstract per
ereditare le funzionalità necessarie al corretto
funzionamento della classe.
●
Le classi di cui abbiamo bisogno per la gestione del
nostro blog sono tre:
●
User
●
Post
●
Comment
|
| 31
Zend Framework dalla A alla Zend
mar 2008
36
38. post.php
class post extends Zend_Db_Table_Abstract
{
protected $_name = 'post';
protected $_primary = 'id';
protected $_dependentTables = array('comment');
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
38
39. comment.php
class comment extends Zend_Db_Table_Abstract
{
protected $_name = 'comment';
protected $_primary = 'id';
protected $_referenceMap = array('Post' => array(
'columns' => 'post',
'refTableClass' => 'post',
'refColumns' => 'id'
));
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
39
40. Collegamenti tra tabelle
●
Utilizzando $_dependantTables e $_referenceMap
abbiamo creato un collegamento tra la tabella dei post e
quella dei commenti.
●
In questo modo possiamo facilmente estrarre tutti i
commenti collegati a ciascun post utilizzando il metodo
findDependentRowset che estrae automaticamente
tutte le rige della tabella collegata secondo quanto
specificato in $_referenceMap
|
| 31
Zend Framework dalla A alla Zend
mar 2008
40
41. Estraiamo i dati
●
Creiamo un nuovo controller che si chiama
PostController
●
Creiamo l'azione listAction() che si occuperà di
estrarre i post e mostrarli all'utente.
public function listAction()
{
$post = new post();
$results = $post>fetchAll(null,'date DESC');
$this>view>posts = $results;
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
41
42. list.phtml
<?php foreach ($this>posts as $post): ?>
<div class=quot;postquot;>
<div class=quot;post_mainquot;>
<div class=quot;post_titlequot;>
<?php echo $post>title ?>
</div>
<div class=quot;post_datequot;>
Post inviato il <?php echo $this>FormatDate($post>date) ?>
da <?php echo $this>UserInfo($post>user)>name ?> <?php
echo $this>UserInfo($post>user)>surname ?>
</div>
<div class=quot;post_abstractquot;>
<?php echo $post>abstract ?>
</div>
</div>
|
| 31
Zend Framework dalla A alla Zend
mar 2008
42
43. list.phtml
<div class=quot;post_infoquot;>
<div class=quot;post_infoTitlequot;>AZIONI SUL POST</div>
<div class=quot;post_InfoMainquot;>
Contatta l'autore:<a href='mailto:<?php echo $this
>UserInfo($post>user)>email ?>'>
<?php echo $this>UserInfo($post>user)>email ?></a><br /
><br/>
<?php echo $this>PostMenu($post>id) ?>
</div>
</div>
<div class=quot;clearquot;></div>
</div>
<?php endforeach; ?>
|
| 31
Zend Framework dalla A alla Zend
mar 2008
43
44. View Helper
• Nelle viste sarà spesso necessario eseguire operazioni
complesse come ad esempio formattare una data o
generare elementi di un form. Zend Framework ci
permette di creare delle classi che ci aiutino ad eseguire
queste operazioni.
• C'è un ampio set di view helper builtin in Zend
Framework come ad esempio quelli riguardanti la
creazione di un form.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
44
45. Custom View Helper
• FormatDate, UserInfo e PostMenu sono View Helper
Custom creati ad hoc per il nostro progetto.
• L'helper che creiamo sarà una classe chiamata
Zend_View_Helper_customhelper definita nel file
customhelper.php all'interno della cartella degli helper
(dove customhelper è il nome che vogliamo utilizzare).
|
| 31
Zend Framework dalla A alla Zend
mar 2008
45
46. UserInfo.php
class Zend_View_Helper_UserInfo
{
function UserInfo($userid)
{
$user = new user();
$info = $user>find($userid);
return $info>current();
}
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
46
47. FormatDate.php
class Zend_View_Helper_FormatDate
{
public function FormatDate($date)
{
$date = new
Zend_Date($date,Zend_Date::TIMESTAMP);
return $date>toString(quot;dd MMMM yyyy 'alle'
HH:mmquot;);
}
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
47
49. Implementiamo l'autenticazione
• Creiamo un nuovo controller LoginController per gestire
l'autenticazione.
• Avremo bisogno di un'azione che visualizzi un form per
l'inserimento delle credenziali.
• E di un'altra azione che effettivamente controlli i dati
sull'adapter specificato.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
49
50. Creiamo il form
• Per la creazione del form utilizziamo Zend_Form.
• Creiamo un nuovo metodo protetto all'interno di
LoginController che chiameremo _getForm().
• Questo metodo ci sarà utile per recuperare l'oggetto del
form in qualsiasi azione del nostro controller anche per
effettuare la validazione dei dati inviati.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
50
51. Il metodo _getForm()
protected function _getForm()
{
$form = new Zend_Form();
$form>setAction('/login/login');
$form>setMethod('post');
$form>addElement('text','email',
array('Required'=>true,'Label'=>'Email'));
$form>addElement('password','password',
array('Required'=>true,'Label'=>'Password'));
$form>addElement('submit','login',array('label'=>'Entra'));
return $form;
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
51
52. Visualizziano il form
function indexAction()
{
$form = $this>_getForm();
echo $form>render();
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
52
53. Effettuiamo il login
function loginAction()
{
$form = $this>_getForm();
if($form>isValid($_POST))
{
$db = Zend_Registry::get('db');
$email = $form>getValue('email');
$password = $form>getValue('password');
$auth = Zend_Auth::getInstance();
$authAdapter = new Zend_Auth_Adapter_DbTable
($db,'user','email','password','MD5(?)');
$authAdapter>setIdentity($email)
>setCredential($password);
|
| 31
Zend Framework dalla A alla Zend
mar 2008
53
54. Effettuiamo il login
$authResult = $auth>authenticate($authAdapter);
$auth>getStorage()>write(
$authAdapter>getResultRowObject(array('id','email')));
if($authResult>isValid())
{
$this>_redirect('/post/list');
}
else
{
$auth>clearIdentity();
$this>view>error = 'Username o Password errati.';
echo $form>render();
}
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
54
55. Effettuiamo il login
else
{
echo $form>render();
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
55
56. Creiamo la nostra ACL
• Per creare la nostra Access Control List scriviamo una
classe AccessControl derivata da Zend_Acl.
• In questa classe andremo a definire Risorse, Ruoli e
Permessi.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
56
57. AccessControl.php
class AccessControl extends Zend_Acl
{
public function __construct()
{
$guest = new Zend_Acl_Role('guest');
$member = new Zend_Acl_Role('member');
$this>addRole($guest);
$this>addRole($member);
$this>add(new Zend_Acl_Resource('index'));
$this>add(new Zend_Acl_Resource('login'));
$this>add(new Zend_Acl_Resource('post'));
$this>add(new Zend_Acl_Resource('comment'));
|
| 31
Zend Framework dalla A alla Zend
mar 2008
57
58. AccessControl.php
$this>allow('guest','login');
$this>allow('guest','index');
$this>allow('guest','post',array('list','view'));
$this>allow('member','index');
$this>allow('member','login');
$this>allow('member','post',
array('list','new','save','view','delete'));
$this>allow('member','comment',array('list','new','save'));
}
}
|
| 31
Zend Framework dalla A alla Zend
mar 2008
58
59. Meccanismo di autenticazione
• L'autenticazione dell'utente e la verifica dei permessi
associati al ruolo dovranno ovviamente essere fatti per
ogni richiesta dell'utente.
• L'architettura del controller include un sistema di plugin
che permette all'utente di eseguire codice
all'occorrenza di alcuni eventi durante il processo
dei dispatch dell'applicazione.
• Utilizzeremo un plugin per eseguire ad ogni richiesta il
controllo dei permessi dell'utente sulla risorsa richiesta.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
59
63. Inserimento di un nuovo post
• Creiamo una nuova azione in PostController che
chiameremo newAction()
• Come per il login abbiamo bisogno di un form che
raccolga i dati da utilizzare. Creiamo quindi il metodo
_getForm all'interno di PostController.
• Creiamo poi una nuova azione che salvi i dati nel
database che chiameremo saveAction()
• saveAction controlla i dati inviati tramite il form e li
inserisce utilizzando il metodo insert di
Zend_Db_Table
|
| 31
Zend Framework dalla A alla Zend
mar 2008
63
64. Visualizzazione post
• Creiamo una nuova azione in PostController che
chiameremo viewAction()
• Dobbiamo passare un parametro all'azione che
rappresenta l'id del post da visulizzare.
• Estraiamo i dati utilizzando il metodo find di
Zend_Db_Table e ed estraiamo tutti i commenti
utilizzando findDependentRowset
|
| 31
Zend Framework dalla A alla Zend
mar 2008
64
65. Inserimento di un commento
• Creiamo un nuovo controller CommentController ed
una nuova azione all'interno che chiameremo
newAction()
• Come per il login abbiamo bisogno di un form che
raccolga i dati da utilizzare. Creiamo quindi il metodo
_getForm all'interno di CommentController.
• Creiamo poi una nuova azione che salvi i dati nel
database che chiameremo saveAction()
• saveAction controlla i dati inviati tramite il form e li
inserisce utilizzando il metodo insert di
Zend_Db_Table
|
| 31
Zend Framework dalla A alla Zend
mar 2008
65
66. Creazione dei menu
• Abbiamo bisogno di due menu per permettere la
navigazione dell'utente.
• Un menu principale per spostarsi attraverso le pagine
del blog
• Entra/Esci
• Blog
• Nuovo post
• Un menu per il post per effettuare azioni sul post.
• Aggiungi un commento
• Elimina il post
|
| 31
Zend Framework dalla A alla Zend
mar 2008
66
67. Creazione dei menu
• All'interno dei menu dovremo utilizzare le tecniche
apprese in precedenza per controllare i permessi
associati al ruolo dell'utente in modo da visualizzare
solo i link per le pagine che l'utente può visualizzare.
• Per fare questo utilizziamo Zend_Auth e Zend_Acl:
• Il primo per prendere l'identità dell'utente e quindi
anche il ruolo.
• Il secondo per verificare con il metodo idAllowed se
quel ruolo può visulizzare una determinata risorsa.
|
| 31
Zend Framework dalla A alla Zend
mar 2008
67
68. THANK YOU
“
Zend Framework
Simplicity, Meet Power
massimiliano@zend.com