<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hello World: &#187; applicazioni con zend framework</title>
	<atom:link href="http://razorblade.netsons.org/tag/applicazioni-con-zend-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://razorblade.netsons.org</link>
	<description>Programmazione web e oltre: php5, Zend Framework, jQuery, Actionscript 3.0, Sandy 3D Engine e altro</description>
	<lastBuildDate>Fri, 28 Aug 2009 18:23:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Zend Search Lucene e UTF-8 Unicode con Zend Framework</title>
		<link>http://razorblade.netsons.org/2008/10/27/zend-search-lucene-e-utf-8-unicode-con-zend-framework/</link>
		<comments>http://razorblade.netsons.org/2008/10/27/zend-search-lucene-e-utf-8-unicode-con-zend-framework/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 04:12:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Apache Lucene project]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[charset]]></category>
		<category><![CDATA[multibyte]]></category>
		<category><![CDATA[php_mbstring]]></category>
		<category><![CDATA[uft8_decode]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[UTF-8]]></category>
		<category><![CDATA[utf8_encode]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[Zend_Search_Lucene]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=43</guid>
		<description><![CDATA[<h2>Visualizzare e ricercare correttamente stringhe multibyte</h2>

<p>In questo articolo riprendiamo ciò che si era detto in <a href="http://razorblade.netsons.org/2008/09/30/zend-search-lucene-applicazione-reale-zend-framework-p10/">quest'altro articolo</a> a proposito del componente Zend_Search_Lucene, facendo delle importanti aggiunte riguardo la gestione dell'indicizzazione e ricerca di stringhe multibyte, ovvero di quelle stringhe contenenti testo in lingue tipo russo, cinese, giapponese ecc... Inoltre anche il noto problema dei caratteri accentati è eliminato per sempre. <a href="http://razorblade.netsons.org/2008/10/27/zend-search-lucene-e-utf-8-unicode-con-zend-framework/">[...] Continua</a></p>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/04/24/luke-lucene-index-toolbox-di-andrzej-bialecki-per-zend_search_lucene/' rel='bookmark' title='Permanent Link: Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene'>Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene</a> <small>Verificare il contenuto dell'indice di Lucene Se avete seguito questo...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Visualizzare e ricercare correttamente stringhe multibyte</h2>
<p>In questo articolo riprendiamo ciò che si era detto in <a href="http://razorblade.netsons.org/2008/09/30/zend-search-lucene-applicazione-reale-zend-framework-p10/">quest&#8217;altro articolo</a> a proposito del componente Zend_Search_Lucene, facendo delle importanti aggiunte riguardo la gestione dell&#8217;indicizzazione e ricerca di stringhe multibyte, ovvero di quelle stringhe contenenti testo in lingue tipo russo, cinese, giapponese ecc&#8230; Inoltre anche il noto problema dei caratteri accentati è eliminato per sempre. </p>
<p>Prima però vedremo come implementare la corretta visualizzazione di queste effettuando alcune modifiche al codice php ed html ma anche al database.</p>
<p>Questo articolo non vuole essere una spiegazione approfondita su cosa sia un stringa multibyte, sui charset esistenti e sulla loro storia, se non siete a conoscenza di cosa stia parlando forse è meglo effettuare prima una <a href="http://www.google.it/search?hl=it&#038;q=unicode+multibyte+utf8&#038;btnG=Cerca&#038;meta=lr%3Dlang_it">ricerca</a>.
</p>
<p>Al termine di questo articolo è presente il progetto completo di tutti gli sviluppi e modifiche discusse sino ad oggi</p>
<p><h2>Database ed UTF-8</h2>
</p>
<p>UTF-8 è una codifica Unicode multi-byte ASCII-compatibile, ed è la codifica che utilizzeremo come standard per il nostro progetto. Per creare un database MySql che utilizzi UTF-8 dovremo specificare il set di caratteri MySQL utf8_unicode_ci come collation all&#8217;atto della creazione del database.</p>
<pre name="code" class="php">
CREATE DATABASE `miodb` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
</pre>
</p>
<p>Lo stesso genere di collation dovrà essere specificato per i campi di testo contenuti all&#8217;interno delle tabelle del database, in ogni caso è una cosa che avviene automaticamente utilizzando PhpMyAdmin.</p>
<h2>Salvataggio dei dati</h2>
<p>All&#8217;atto dell&#8217;inserimento e modifica dei dati, dovremmo fare molta attenzione che questi siano encodati prima di essere inseriti. In una normale applicazione potremmo ricorrere all&#8217;utilizzo delle funzioni <a href="http://it.php.net/manual/it/function.utf8-encode.php">utf8_encode</a> ed <a href="http://it.php.net/manual/it/function.utf8-decode.php">utf8_decode</a>, rispettivamente per la codifica ( prima del salvataggio ) e la decodifica ( dopo essere state recuperati dal db ), in Zend Framework la codifica UTF-8 viene gestita internamente, quindi non dovremo utilizzare queste funzioni per inserire dati nel database. Tuttavia le utilizzeremo per decodificare i record estratti dal database prima dell&#8217;inserimento nell&#8217;indice di Lucene.</p>
<p><h2>Il codice HTML</h2>
</p>
<p>Infine dovremmo specificare nel tag HEAD il corretto META per il charset</p>
<pre name="code" class="php">
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
</pre>
<h2>Modifiche al codice di Lucene</h2>
<p>Qui di seguito vedremo passo passo le modifiche effettuate al codice in qualche modo relazionato con la gestione di Zend_Search_Lucene. Tutte queste modifiche sono incluse nel file in download, quindi non inserirò il file nella sua completezza.</p>
<p>Per prima cosa modifichiamo il metodo getSearchIndexFields nella classe Paese, la classe row level di Paesi.</p>
<pre name="code" class="php">
    public function getSearchIndexFields(){
      $user = $this->findParentRow('Utenti');
      $reviews = $this->findRecensioni();
      $result = array();
      $result['class'] = 'Paese';
      $result['key'] = $this->id;
      $result['title'] = $this->nome;
      $result['contents'] = $this->provincia;
      $result['summary'] = "";
      if(count($reviews) > 0){
        foreach($reviews as $review) {
          $result['contents'] .= "\n".utf8_decode($review->descrizione);
          $result['summary'] .= "\n".mb_substr($review->descrizione,0,40);
        }
      }
      $result['createdBy'] = $user->name;
      $result['dateCreated'] = $this->inserimento_data;
      return $result;
    }
</pre>
<p>Per fare in modo di indicizzare correttamente il contenuto del database, codificato in UTF-8, dobbiamo prima decodificarlo. Il campo testuale che subisce la decodifica è il campo contenente il corpo di una probabile recensione. Da notare che la chiave &#8217;summary&#8217; contiene un&#8217;anteprima di quello che contiene la recensione, ovvero i primi 40 caratteri. Siccome si tratta di un campo multibyte, utilizziamo la funzione <a href="http://it.php.net/manual/it/function.mb-substr.php">mb_substr</a>. Notate che l&#8217;utilizzo delle funzioni multibyte richiede che sia installata la relativa estensione per php ( per chi usa WampServer in locale: PHP -> PHP Extension -> php_mbstring ).</p>
<p>Infine aggiungiamo 2 righe di codice al bootstrap index.php:</p>
<pre name="code" class="php">
  Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('UTF-8');
  Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8());
</pre>
<p>Con questo codice diciamo a Lucene di interpretare le eventuali stringhe di ricerca come stringhe UTF-8 e di utilizzare il medesimo encoding per la gestione dei documenti nel suo indice, per maggiori informazioni potete consultare la <a href="http://framework.zend.com/manual/en/zend.search.lucene.charset.html#zend.search.lucene.charset.description">guida ufficiale</a>.</p>
<h2>Conclusione</h2>
<p>Ho apportato diverse altre modifiche al codice, ad esempio allo stile e ad alcune views. Inoltre ho aggiunto il supporto per la gestione degli errori 404 ( file non trovato ) e degli errori dell&#8217;applicazione, che vedremo in un prossimo articolo.</p>
<p>Come annunciato, potete tra poco scaricare il progetto comprensivo di database con alcuni dati di esempio in 4 lingue diverse, italiano, giapponese, russo e hindi ( o almento credo.. )</p>
<p>Non sono presenti link che rimandano ai controllers presenti ma se avete letto gli articoli passati dovreste sapere quali sono&#8230; in ogni caso i controller attualmente presenti sono:</p>
<ul class="listato">
<li>index ( ovviamente )</li>
<li>search</li>
<li>supporto</li>
<li>paese</li>
<li>auth</li>
<li>ajax</li>
</ul>
<p>Avete inoltre bisogno delle seguenti informazioni:</p>
<ul class="listato">
<li>username e password per accedere sono Admin &#8211; admin</li>
<li>il controller supporto invia email ( anche da locale ) se inserite le credenziali di un account email compatibile</li>
<li>prima di effettuare ricerche dovete richiamare la reindex action del search controller</li>
</ul>
<h2><a href="http://razorblade.netsons.org/files/paesidelmondo.rar">DOWNLOAD</a></h2>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/04/24/luke-lucene-index-toolbox-di-andrzej-bialecki-per-zend_search_lucene/' rel='bookmark' title='Permanent Link: Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene'>Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene</a> <small>Verificare il contenuto dell'indice di Lucene Se avete seguito questo...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/10/27/zend-search-lucene-e-utf-8-unicode-con-zend-framework/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>Zend Search Lucene ( applicazione reale Zend Framework p.10 )</title>
		<link>http://razorblade.netsons.org/2008/09/30/zend-search-lucene-applicazione-reale-zend-framework-p10/</link>
		<comments>http://razorblade.netsons.org/2008/09/30/zend-search-lucene-applicazione-reale-zend-framework-p10/#comments</comments>
		<pubDate>Mon, 29 Sep 2008 23:07:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Apache Lucene project]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[full text]]></category>
		<category><![CDATA[Observer Pattern]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[Zend_Search_Lucene]]></category>
		<category><![CDATA[Zend_Search_Lucene_Document]]></category>
		<category><![CDATA[Zend_Search_Lucene_Field]]></category>
		<category><![CDATA[Zend_Search_Lucene_Search_QueryHit]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=35</guid>
		<description><![CDATA[<h2>Il componente Zend_Search_Lucene</h2>
<p>La possibilità di poter effettuare una ricerca che restituisca quello che stavamo cercando con il minimo sforzo è una caratteristica essenziale per un sito che si rispetti. Zend Framework ci viene incontro con il componente <b>Zend_Search_Lucene</b>, un motore di ricerca di tipo <b>full text</b> basato sull' <a href="http://lucene.apache.org/java/docs/" title="Apache Lucene project">Apache Lucene project</a>, un motore di ricerca per Java.</p>

<p>Zend_Search_Lucene crea un <b>indice</b> di documenti. Questo indice viene salvato direttamente nel filesystem, in una directory a nostra scelta, senza la necessità di avere <a href="http://razorblade.netsons.org/2008/09/30/zend-search-lucene-applicazione-reale-zend-framework-p10/">[...] Continua</a></p>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/04/24/luke-lucene-index-toolbox-di-andrzej-bialecki-per-zend_search_lucene/' rel='bookmark' title='Permanent Link: Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene'>Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene</a> <small>Verificare il contenuto dell'indice di Lucene Se avete seguito questo...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Il componente Zend_Search_Lucene</h2>
<p>La possibilità di poter effettuare una ricerca che restituisca quello che stavamo cercando con il minimo sforzo è una caratteristica essenziale per un sito che si rispetti. Zend Framework ci viene incontro con il componente <b>Zend_Search_Lucene</b>, un motore di ricerca di tipo <b>full text</b> basato sull&#8217; <a href="http://lucene.apache.org/java/docs/" title="Apache Lucene project">Apache Lucene project</a>, un motore di ricerca per Java.</p>
<p>Zend_Search_Lucene crea un <b>indice</b> di documenti. Questo indice viene salvato direttamente nel filesystem, in una directory a nostra scelta, senza la necessità di avere a disposizione un database server. Tra le caratteristiche possiamo elencare:</p>
<ul class='listato'>
<li>Ricerca per indice di coerenza: i risultati di maggior rilievo vengono restituiti in cima alla lista</li>
<li>Possibilità di utilizzo di numerosi metodi di ricerca: phrase queries, boolean queries, wildcard queries, proximity queries, range queries e molte altre.</li>
<li>Ricerca per un campo specifico (ad esempio titolo, autore, descrizione )</li>
</ul>
<h2>Tipi di campo</h2>
<table border="1" summary="Zend_Search_Lucene_Field Types">
<colgroup>
<col />
<col />
<col />
<col />
<col />
  </colgroup>
<thead>
<tr>
<th>Field Type</th>
<th>Stored</th>
<th>Indexed</th>
<th>Tokenized</th>
<th>Binary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Keyword</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>UnIndexed</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Binary</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Text</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>UnStored</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
</tr>
</tbody>
</table>
<p>Questa tabella ci mostra i tipi di campo che possiamo inserire nell&#8217;indice di Zend_Search_Lucene e come questi vengono trattati. Vediamoli più nel dettaglio:</p>
<ul class='listato'>
<li><b>Keyword</b> I campi indicati come keyword sono memorizzati e indicizzati, il che significa che possono essere ricercati e visualizzati tra i risultati di ricerca. Le parole dei campi keyword devono essere separate. Dei buoni candidati per questo tipo di campo sono ad esempio i campi enumerated.</li>
<li><b>UnIndexed</b> I campi UnIndexed non sono ricercabili ma vengono ritornati tra i risultati di ricerca. Buoni candidati ad appartenere a questa tipologia di campo sono, ad esempio, i campi chiave primaria, i timestamps, percorsi di filesystem.</li>
<li><b>Binary</b> I campi Binary non sono indicizzati ma possono essere ritrovati tra i risultati di ricerca. Vi appartengono quei dati salvati come stringa binaria, ad esempio una icona o una thumbnail.</li>
<li><b>Text</b> I campi Text sono memorizzati ed indicizzati, quindi saranno utili ai fini della ricerca ed inoltre saranno restituiti tra i risultati. Ne fanno parte, per eempio, quei campi che contengono titoli, descrizioni ecc, quindi varchar, text ecc.</li>
<li><b>UnStored</b> I campi di tipo UnStored sono indicizzati ma non sono memorizzati nell&#8217;indice. Questo genere di campo è da utilizzarsi per testi molto lunghi, in quanto, pur essendo ricercabili, non occupano spazio su disco. Nel caso si utilizzi un database, i dati per la visualizzazione potranno essere recuperati da questo.</li>
</ul>
<h2>Come Funziona</h2>
<p>Il funzionamento di Zend_Search_Lucene e del suo indice è rappresentato dal seguente schema</p>
<p>Ogni documento inserito nell&#8217;indice è una istanza di <b>Zend_Search_Lucene_Document</b>, ed ogni documento contiene degli oggetti di tipo <b>Zend_Search_Lucene_Field</b>, che contengono i dati. Dopo aver effettuato la query il risultato ritornato è un array contenente dei risultati, ognuno di questi un oggetto di tipo <b>Zend_Search_Lucene_Search_QueryHit</b>.</p>
<h2>Unificare i documenti</h2>
<p>L&#8217;indice può contenere dei documenti di tipi differenti, come pagine, recensioni, profili utente ecc. Per fare in modo che i risultati di ricerca siano comprensibili per l&#8217;utente dobbiamo unificarli, ovvero scegliere quali campi comuni inserire nel documento dell&#8217;indice. Il seguente  un esempio di unificazione dei documenti da aggiungere all&#8217;indice:</p>
<table border=1>
<colgroup>
<col />
<col />
<col />
  </colgroup>
<thead>
<tr>
<th>Field Name</th>
<th>Type</th>
<th>Notes</th>
</tr>
</thead>
<tr>
<td>class</td>
<td>UnIndexed</td>
<td>La classe a cui appartengono i dati memorizzati. Abbiamo necessità di conoscerla in quanto è necessaria per creare la corretta url per il documento.</td>
</tr>
<tr>
<td>key</td>
<td>UnIndexed</td>
<td>La chiave per i dati memorizzati. Solitamente è l&#8217;id del record. Abbiamo necessità di conoscerla in quanto è necessaria per creare la corretta url per il documento.</td>
</tr>
<tr>
<td>docRef</td>
<td>Keyword</td>
<td>Un identificatore univoco per il record. Servirà al fine di modifica ed eliminazione</td>
</tr>
<tr>
<td>title</td>
<td>Text</td>
<td>Il titolo del record utile ai fini di ricerca e di visualizzazione</td>
</tr>
<tr>
<td>contents</td>
<td>UnStored</td>
<td>Il contenuto principale del record. Ricercabile ma come detto in precedenza non memorizzato in quanto questo potrebbe essere un gran quantitativo di testo che appesantirebbe troppo l&#8217;indice.</td>
</tr>
<tr>
<td>summary</td>
<td>UnIndexed</td>
<td>Contiene informazioni per la visualizzazione. Non è utile al fine della ricerca.</td>
</tr>
<tr>
<td>createdBy</td>
<td>Text</td>
<td>Creatore del documento. Memorizzato e ricercabile.</td>
</tr>
<tr>
<td>dateCreated</td>
<td>Keyword</td>
<td>Data di creazione. Non necessita di essere parsato da Lucene ( Tokenized NO ) ma è memorizzato ed utile al fine della ricerca.</td>
</tr>
</table>
<h2>Creazione di un documento</h2>
<p>Come detto in precedenza, ogni documento è una istanza della classe Zend_Search_Lucene_Document. Siccome siamo giunti al punto di avere il design del documento ben definito ( la tabella di qui sopra ), possiamo procedere con il creare una classe personalizzata che estenda Zend_Search_Lucene_Document che ci semplifichi la creazione di un documento. La classe in questione si chiamerà Paesidelmondo_Search_Lucene_Document</p>
<p><b>Paesidelmondo_Search_Lucene_Document</b></p>
<pre name="code" class="php">
  class Paesidelmondo_Search_Lucene_Document extends Zend_Search_Lucene_Document {
    public function __construct($class, $key, $title,  $contents, $summary, $createdBy, $dateCreated) {
      $this->addField(Zend_Search_Lucene_Field::Keyword( 'docRef', $class.":".$key));
      $this->addField(Zend_Search_Lucene_Field::UnIndexed( 'class', $class));
      $this->addField(Zend_Search_Lucene_Field::UnIndexed( 'key', $key));
      $this->addField(Zend_Search_Lucene_Field::Text( 'title', $title));
      $this->addField(Zend_Search_Lucene_Field::UnStored( 'contents', $contents));
      $this->addField(Zend_Search_Lucene_Field::UnIndexed( 'summary', $summary));
      $this->addField(Zend_Search_Lucene_Field::Keyword( 'createdBy', $createdBy));
      $this->addField(Zend_Search_Lucene_Field::Keyword( 'dateCreated', $dateCreated));
    }
  }
</pre>
<p>La classe è molto semplice e contiene solo il costruttore a cui passeremo il valore dei campi del documento.</p>
<p>Il problema successivo è creare i documenti ed aggiungerli all&#8217;indice. Il seguente esempio, mostra come fare:</p>
<pre name="code" class="php">
$index = Zend_Search_Lucene::open($path);
$doc = new Paesidelmondo_Search_Lucene_Document(
  $class, $key,
  $title, $contents,
  $summary, $createdBy, $dateCreated
);
$index->addDocument($doc);
</pre>
<p>Quello che adesso bisogna fare è ripetere questo codice per ogni classe modello a cui la funzionalità di ricerca debba essere applicata. Ogni modelo chiaramente conosce tutto a proposito dei dati da ricercare, quello che non sa è come aggiungere questi dati all&#8217;indice del motore di ricerca, in quanto, se lo sapesse, sarebbe troppo strettamente legato ad esso e renderebbe difficile un eventuale sostituzione del motore di ricerca con un altro. La soluzione di questo problema è l&#8217;utilizzo di un design pattern chiamato <b>Observer Pattern</b></p>
<h2>Observer Pattern</h2>
<p>L&#8217;Observer Pattern utilizza il concetto di notifica. Un oggetto detto <b>observer</b> registra interesse verso un altro oggetto, detto <b>observable</b> e quando qualcosa succede ad <b>observable</b>, l&#8217;oggetto <b>observer</b> prende le azioni appropriate. Le nostre classi observable sono i nostri modelli ed i dati a cui siamo interessati sono istanze di Zend_Db_Table_Row_Abstract, quindi la estendiamo creando Paesidelmondo_Db_Table_Row_Observerable.</p>
<pre name="code" class="php">
  class Paesidelmondo_Db_Table_Row_Observerable extends Zend_Db_Table_Row_Abstract {
    protected static $_observers = array();

    public static function attachObserver($class){
      if (!is_string($class) || !class_exists($class) || !is_callable(array($class , 'observeTableRow'))) {
        return false;
      }
      if (!isset(self::$_observers[$class])) {
        self::$_observers[$class] = true;
      }
      return true;
    }

    public static function detachObserver($class){
      if (!isset(self::$_observers[$class])) {
        return false;
      }
      unset(self::$_observers[$class]);
      return true;
    }

    protected function notifyObservers($event){
      if (!empty(self::$_observers)) {
        foreach (array_keys(self::$_observers) as $observer) {
          call_user_func(array($observer , 'observeTableRow'), $event, $this);
        }
      }
    }

    protected function _insert(){
      self::notifyObservers('pre-insert');
    }

    protected function _postInsert(){
      self::notifyObservers('post-insert');
    }

    protected function _update(){
      self::notifyObservers('pre-update');
    }

    protected function _postUpdate(){
      self::notifyObservers('post-update');
    }

    protected function _delete(){
      self::notifyObservers('pre-delete');
    }

    protected function _postDelete(){
      self::notifyObservers('post-delete');
    }
  }
</pre>
<p>Questa classe contiene la proprietà statica $_observers in quanto la lista degli observers è indipendente dal modello, quindi per qualsiasi modello deve poter essere recuperata la stassa lista di observers. Il metodo statico attachObserver è quello che registra un oggetto observer e lo inserisce all&#8217;interno dell&#8217;array statico solo dopo aver effettuato alcuni controlli. La registrazione dell&#8217;oggetto observer dev&#8217;essere fatta nel bootstrap, vedremo tra non molto l&#8217;oggetto observer ed il codice da inserire nel bootstrap.</p>
<p>Il metodo detachObserver serve a rimuovere un observer precedentemente registrato e quindi giungiamo al metodo notifyObservers che richiama il metodo observeTableRow per ogni observer presente nell&#8217;array degli observer registrati, passandogli inoltre, il nome dell&#8217;evento e l&#8217;istanza del modello che ha scatenato l&#8217;evento. </p>
<h2>L&#8217;oggetto Observer</h2>
</p>
<p>L&#8217;oggetto che utilizzeremo come observer si chiamerà <b>SearchIndexer</b> ed in quanto è un modelo sarà salvato in application/models</p>
<p><b>application/models/</b><b>SearchIndexer</b></p>
<pre name="code" class="php">
  class SearchIndexer { 

    protected static $_indexDirectory;

    public static function setIndexDirectory($directory){
    	if(!is_dir($directory)) {
    		throw new Exception('Directory for SearchIndexer is invalid ('. $directory .')');
    	}
    	self::$_indexDirectory = $directory;
    }

    public static function getIndexDirectory(){
    	return self::$_indexDirectory;
    }

    public static function observeTableRow($event, $row){
      switch($event){
        case 'post-insert':
        case 'post-update':
          $doc = self::getDocument($row);
          if ($doc !== false){
            self::_addToIndex($doc);
          }
        break;
      }
    }

    public static function getDocument($row) {
      if(method_exists($row, 'getSearchIndexFields')){
        $fields = $row->getSearchIndexFields($row);
        $doc = new Paesidelmondo_Search_Lucene_Document(
          $fields['class'], $fields['key'],
          $fields['title'], $fields['contents'],
          $fields['summary'], $fields['createdBy'],
          $fields['dateCreated']
        );
        return $doc;
      }
      return false;
    }

    protected static function _addToIndex($doc){
      try {
        $index = Paesidelmondo_Search_Lucene::open(self::$_indexDirectory);
      } catch (Exception $e) {
        $index = Paesidelmondo_Search_Lucene::create(self::$_indexDirectory);
      }
      $index->addDocument($doc);
      $index->commit();
    }
  }
</pre>
<p>L&#8217;oggetto SearchIndexer è l&#8217;oggetto <b>observer</b> dell&#8217;oggetto Paesidelmondo_Db_Table_Row_Observerable, che quindi è l&#8217;oggetto <b>observable</b>. I modelli row level per cui vogliamo implementare la funzionalità di ricerca estendono Paesidelmondo_Db_Table_Row_Observerable, quindi ognuno di essi è un oggetto <b>observable</b>.</p>
<p>SearchIndexer contiene al suo interno i seguenti etodi statici, vediamoli nel dettaglio: </p>
<ul class='listato'>
<li><b>setIndexDirectory</b> definisce dove nel filesystem sarà memorizzato l&#8217;indice. Da utilizzarsi nel bootstrap.</li>
<li><b>observeTableRow</b> ogni volta che un oggetto observable viene modificato o creato, observeTableRow viene avvisato, rendendo disponibili il tipo di evento scatenato e l&#8217;oggetto observable. Quindi, in base all&#8217;evento, possono essere effettuate delle modifiche all&#8217;indice, come per esempio l&#8217;aggiunta all&#8217;indice.</li>
<li><b>getDocument</b> questo metodo controlla se l&#8217;oggetto $row ( oggetto observable ) possiede un metodo getSearchIndexField. In caso positivo un documento valido per l&#8217;aggiunta all&#8217;indice viene ritornato. </li>
<li><b>_addToIndex</b> questo metodo si occupa di aggiungere il documento al&#8217;indice</li>
</ul>
<p>Ora non ci resta che vedere un esempio di un modello observable che estenda Paesidelmondo_Db_Table_Row_Observerable, a questo scopo creeremo la classe Paese, il modello row level dell&#8217;oggetto Paesi.</p>
<p>application/models/<b>Paese</b></p>
<pre name="code" class="php">
  class Paese extends Paesidelmondo_Db_Table_Row_Observerable
  {
    public function getSearchIndexFields(){
      $user = $this->findParentRow('Utenti');
      $reviews = $this->findRecensioni();
      $result = array();
      $result['class'] = 'Paese';
      $result['key'] = $this->id;
      $result['title'] = $this->nome;
      $result['contents'] = $this->provincia;
      foreach ($reviews as $review) {
        $result['contents'] .= "\n".$review->descrizione;
      }
      $result['summary'] = substr($review->descrizione,0,40);
      $result['createdBy'] = $user->name;
      $result['dateCreated'] = $this->inserimento_data;
      return $result;
    }

    protected function _insert(){
      if(is_null($this->created_by)) {
        $user = Zend_Auth::getInstance()->getIdentity();
        $this->created_by = (int)$user->id;
      }
      if(is_null($this->date_created)) {
        $this->date_created = date('Y-m-d H:i:s');
      }
      if(is_null($this->date_updated)) {
        $this->date_updated = date('Y-m-d H:i:s');
      }
      parent::_insert();
    }

    protected function _update(){
      $this->date_updated = date('Y-m-d H:i:s');
      parent::_update();
    }
  }
</pre>
<p>Il metodo getSearchIndexFields() ritorna un array contenente i dati utili per la creazione di una istanza di Zend_Search_Lucene_Document. Ogni modello contenente dati indicizzabili dovrebbe contenere questo metodo, in quanto è quello che si occupa di unificare i campi dei dati con i campi del design dell&#8217;indice. Questo metodo è quello che viene richiamato dal metodo SearchIndexer::getDocument ogni volta che un oggetto observable avverte l&#8217;observe che una modifica è avvenuta. Ad ogni chiamata dei metodi _insert e _update, l&#8217;omonimo metodo della classe parente ( Paesidelmondo_Db_Table_Row_Observerable ) viene chiamato, e questo si occuperà di inviare notifica all&#8217;observer indicado l&#8217;evento scatenante.</p>
<h2>Il Bootstrap</h2>
<p>Nel nostro file di bootstrap ( index.php nella root ), dovremo aggiungere le seguenti linee di codice:</p>
<pre name="code" class="php">
  SearchIndexer::setIndexDirectory(ZEND_ROOT.'/var/search_index');
  Paesidelmondo_Db_Table_Row_Observerable::attachObserver('SearchIndexer');
</pre>
<p>Queste definiscono dove nel filesystem salvare l&#8217;indice e registrano l&#8217;oggetto SearchIndexer come oggetto observer per le istanze di Paesidelmondo_Db_Table_Row_Observerable, i modelli observable.</p>
<p>Infine, avrete sicuramente notato che sia per l&#8217;evento di inserimento che per l&#8217;evento di modifica SearchIndexer::observeTableRow aggiunge l&#8217;oggetto nell&#8217;indice, ma non lo modifica mai. Questo comportamento perchè Zend_Search_Lucene lo estenderemo in modo tale che il metodo addDocument, prima di effettuare un inserimento di un documento nell&#8217;indice controlli la sua esistenza, ed in caso, lo elimini prima di reinserirlo.</p>
<pre name="code" class="php">
  class Paesidelmondo_Search_Lucene extends Zend_Search_Lucene { 

    public static function create($directory){
      return new Zend_Search_Lucene_Proxy(new Paesidelmondo_Search_Lucene($directory, true));
    }

    public static function open($directory){
      return new Zend_Search_Lucene_Proxy(new Paesidelmondo_Search_Lucene($directory, false));
    }

    public function addDocument(Zend_Search_Lucene_Document $document){
      // check document doesn't already exist - docRef should be unique
      $docRef = $document->docRef;
      $term = new Zend_Search_Lucene_Index_Term($docRef, 'docRef');
      $query = new Zend_Search_Lucene_Search_Query_Term($term);
      $results = $this->find($query);
      if(count($results) > 0) {
        foreach($results as $result){
          $this->delete($result->id);
        }
      }
      return parent::addDocument($document);
    }
  }
</pre>
<p>Nel caso non lo abbiate notato, sarà chiamato Paesidelmondo_Search_Lucene piuttosto che Zend_Search_Lucene in quanto in SearchIndexer::_addToIndex viene richiamata la prima e non la seconda, quindi la nuova funzionalità di addDocument è già presente nel codice postato senza dover effettuare altre modifiche.</p>
<h2>Il controller searchController</h2>
<p>Ogni volta che si effettuerà una ricerca, il risultato di questa sarà visualizzato dall&#8217;index action del searchController. Inoltre il searchController conterrà la reindexAction, action con la quale si potranno reindicizzare tutti i documenti indicizzabili.</p>
<p>application/controllers/<b>SearchController.php</b></p>
<pre name="code" class="php">
  class SearchController extends Zend_Controller_Action {
    public function init(){
      $response = $this->getResponse();
      $response->insert('header', $this->view->render('header.phtml'));
      $response->insert('menu', $this->view->render('menu.phtml'));
      $response->insert('columnLeft', $this->view->render('columnLeft.phtml'));
      $response->insert('columnRight', $this->view->render('columnRight.phtml'));
      $response->insert('footer', $this->view->render('footer.phtml')); 

      // [ eventuale controllo di verifica ACL ]
    }

    public function indexAction() {
      $this->view->title = 'Search Results';
      $filters = array('q' => array('StringTrim' , 'StripTags'));
      $validators = array('q' => array('presence' => 'required'));
      $input = new Zend_Filter_Input($filters, $validators, $_GET);
      if ($input->isValid()) {
        $this->view->messages = '';
        $q = $input->getEscaped('q');
        $this->view->q = $q;
        try {
          $index = Paesidelmondo_Search_Lucene::open(SearchIndexer::getIndexDirectory());
          $results = $index->find($q);
        } catch (Exception $e) {
          $results = array();
        }
        $this->view->results = $results;
      } else {
        $this->view->messages = $input->getMessages();
      }
    }

    public function reindexAction(){
    	$this->view->title = 'Search Reindex';
    	$messages = array();
    	$index = Paesidelmondo_Search_Lucene::create(SearchIndexer::getIndexDirectory());
    	$paesidelmondo = new Paesi();
    	$paesi = $paesidelmondo->fetchAll();
    	foreach($paesi as $paese) {
    		$doc = SearchIndexer::getDocument($paese);
    		$index->addDocument($doc);
    		$messages[] = 'Added Place: ' . $doc->title . ' - docRef: ' . $doc->docRef;
    	}
    	$messages[] = '';
    	$index->commit();
    	$messages[] = 'Total documents in index: ' . $index->numDocs();
    	$this->view->messages = $messages;
    }
  }
</pre>
<p>Le seguenti sono le view rispettivamente per la index e la reindex action</p>
<p><b>index.phtml</b></p>
<pre name="code" class="php">
  &lt;h1&gt;&lt;?php echo $this-&gt;escape($this-&gt;title);?&gt;&lt;/h1&gt;

  &lt;?php if ($this-&gt;messages) : ?&gt;
    &lt;div id="error"&gt;
      There was a problem:
      &lt;ul&gt;
        &lt;?php foreach ($this-&gt;messages['q'] as $message) : ?&gt;
        &lt;li&gt;&lt;?php echo $message;?&gt;&lt;/li&gt;
        &lt;?php endforeach; ?&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;?php else <img src='http://razorblade.netsons.org/wp-includes/images/smilies/icon_confused.gif' alt=':?' class='wp-smiley' /> &gt;
    &lt;p&gt;You searched for &lt;?php echo $this-&gt;escape($this-&gt;q); ?&gt;.
    &lt;?php echo count($this-&gt;results);?&gt; results found.
    &lt;/p&gt;

    &lt;ul&gt;
      &lt;?php foreach ($this-&gt;results as $result) : ?&gt;
      &lt;li&gt;&lt;a href="&lt;?php echo $this-&gt;getSearchResultUrl($result-&gt;class, $result-&gt;key); ?&gt;"&gt;
        &lt;?php echo $this-&gt;escape($result-&gt;title);?&gt;&lt;/a&gt;
        &lt;div class="summary"&gt;
        &lt;?php echo $this-&gt;escape($result-&gt;summary);?&gt;
        (&lt;?php echo $result-&gt;score;?&gt;) &lt;/div&gt;
      &lt;/li&gt;
      &lt;?php endforeach; ?&gt;
    &lt;/ul&gt;

  &lt;?php endif; ?&gt;
</pre>
<p><b>reindex.phtml</b></p>
<pre name="code" class="php">
&lt;h1&gt;&lt;?php echo $this-&gt;escape($this-&gt;title);?&gt;&lt;/h1&gt;

&lt;?php foreach ($this-&gt;messages as $message) : ?&gt;
&lt;?php echo $this-&gt;escape($message); ?&gt;&lt;br /&gt;
&lt;?php endforeach; ?&gt;
</pre>
<p>Per concludere ecco il codice del form da inserire dove volete, per esempio nell&#8217;header.php, in modo tale che sia sempre visibile in ogni pagina</p>
<pre name="code" class="php">
&lt;div style="float: right;"&gt;
&lt;h3&gt;Search:&lt;/h3&gt;
&lt;form method="get" action="&lt;?php echo $this-&gt;baseUrl;?&gt;/search"&gt;
 &lt;fieldset&gt;
  &lt;legend&gt;Ricerca&lt;/legend&gt;
  &lt;label for="text"&gt;Nome Utente:&lt;/label&gt;&lt;input type="text" name="q" value=""&gt;
  &lt;input type="submit" name="search" value="Go"&gt;
 &lt;/fieldset&gt;
&lt;/form&gt;
&lt;/div&gt;
</pre>
<p>Si conclude qui la guida al componente Zend_Search_Lucene, ma come spesso accade, non tutto è stato detto! La parte sui possibili identificatori utilizzabili nelle stringhe query e su come effettuare i vari tipi di queries ( Multi-Term Query, Wildcard ecc ) è stata volutamente tralasciata e sarà ripresa in futuro.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/04/24/luke-lucene-index-toolbox-di-andrzej-bialecki-per-zend_search_lucene/' rel='bookmark' title='Permanent Link: Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene'>Luke: Lucene Index Toolbox di Andrzej Bialecki per Zend_Search_Lucene</a> <small>Verificare il contenuto dell'indice di Lucene Se avete seguito questo...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/09/30/zend-search-lucene-applicazione-reale-zend-framework-p10/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Costruire un’applicazione reale con Zend Framework ( parte 9 )</title>
		<link>http://razorblade.netsons.org/2008/09/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-9/</link>
		<comments>http://razorblade.netsons.org/2008/09/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-9/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 11:49:57 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Access Control List]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[autorizzazione]]></category>
		<category><![CDATA[gestione gruppi utenti zend]]></category>
		<category><![CDATA[zend privilege]]></category>
		<category><![CDATA[zend resource]]></category>
		<category><![CDATA[zend role]]></category>
		<category><![CDATA[Zend_Acl]]></category>
		<category><![CDATA[Zend_Acl has]]></category>
		<category><![CDATA[Zend_Acl hasRole]]></category>
		<category><![CDATA[Zend_Acl_Resource]]></category>
		<category><![CDATA[Zend_Acl_Role]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=32</guid>
		<description><![CDATA[<h2>Autorizzazione</h2>
<p>L'<b>autorizzazione</b> è quel processo in cui il sistema stabilisce se un utente loggato ha o meno accesso ad una determinata risorsa. In <b>Zend Framework</b> il processo di autorizzazione è gestito dall'oggetto <b>Zend_Acl</b> ( Access Control List ) .</p>

<p>Prima di procedere con l'implementazione vera e propria, introduciamo alcuni termini che saranno spesso utilizzati parlando di autorizzazione: </p>
<ul class='listato'>
<li><b>Role</b>: con il termine <b>Role</b> ( Ruolo o Gruppo ) si indica un gruppo di utenti</li>
<li><b>Resource</b>: con il termine <b <Resource</b> si indica una risorsa del sistema, come una determinata action di un certo controller o anche solo un dato record, come potrebbe essere una pagina di un sito.</b></li>
<li><b>Privilege</b>: il tipo di accesso richiesto. Per privilegio si intende read, update, insert ecc</li>
</ul>

<a href="http://razorblade.netsons.org/2008/09/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-9/">[...] Continua</a>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Autorizzazione</h2>
<p>L&#8217;<b>autorizzazione</b> è quel processo in cui il sistema stabilisce se un utente loggato ha o meno accesso ad una determinata risorsa. In <b>Zend Framework</b> il processo di autorizzazione è gestito dall&#8217;oggetto <b>Zend_Acl</b> ( Access Control List ) .</p>
<p>Prima di procedere con l&#8217;implementazione vera e propria, introduciamo alcuni termini che saranno spesso utilizzati parlando di autorizzazione: </p>
<ul class='listato'>
<li><b>Role</b>: con il termine <b>Role</b> ( Ruolo o Gruppo ) si indica un gruppo di utenti</li>
<li><b>Resource</b>: con il termine <b <Resource</b> si indica una risorsa del sistema, come una determinata action di un certo controller o anche solo un dato record, come potrebbe essere una pagina di un sito.</b></li>
<li><b>Privilege</b>: il tipo di accesso richiesto. Per privilegio si intende read, update, insert ecc</li>
</ul>
<p>Un ruolo definisce il livello di attività che un utente può compiere all&#8217;interno del sistema, i ruoli in zend framework sono gestiti dall&#8217;oggetto <b>Zend_Acl_Role</b>, come nel seguente esempio:</p>
<pre name="code" class="php">$gruppoUtente = new Zend_Acl_Role('utente'); </pre>
<p>Con la precedente linea di codice abbiamo creato un oggetto che definisce un nuovo gruppo all&#8217;interno del sistema, il gruppo &#8216;utenti&#8217; nel nostro caso, che successivamente andrà aggiunto all&#8217;oggetto Zend_Acl. Da notare che il nome del gruppo una volta creato non può essere più modificato e deve essere un nome unico.</p>
<pre name="code" class="php">
$acl = new Zend_Acl();
$acl->addRole($gruppoUtente);
</pre>
<p>Per ogni ruolo può essere definito un ruolo padre, in modo tale che, il nuovo ruolo creato potrà fare tutto quello che il ruolo parent poteva fare seguendo il concetto di ereditarietà.</p>
<pre name="code" class="php">
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('utente'));
$acl->addRole(new Zend_Acl_Role('moderatore'), 'utente');
</pre>
<p>In questa situazione il gruppo &#8216;moderatore&#8217; può compiere qualsiasi azione legata al gruppo &#8216;utente&#8217; oltre che compiere tutte le azioni ad esso direttamente legate.</p>
<p>Una risorsa è un contenuto in cui vogliamo stabilire e differenziare le regole di accesso. La creazione di una risorsa segue lo stesso procedimento della creazione di un ruolo, l&#8217;oggetto che gestisce le risorse è <b>Zend_Acl_Resource</b>. Poniamo il caso di voler creare la risorsa di un possibile forum del nostro sistema:</p>
<pre name="code" class="php">
$forumResource = new Zend_Acl_Resource('forum');
</pre>
<p>Come per quanto riguarda i ruoli, anche le risorse vanno aggiunte all&#8217;oggetto Zend_Acl, in maniera molto simile per i ruoli, come da questo esempio:</p>
<pre name="code" class="php">
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('utente'));
$acl->addRole(new Zend_Acl_Role('moderatore'), 'utente');
$acl->addResource(new Zend_Acl_Resource('forum'));
$acl->addResource(new Zend_Acl_Resource('posts'), 'forum');
$acl->addResource(new Zend_Acl_Resource('threads'), 'forum');
</pre>
<p>In questo esempio abbiamo creato la risorsa forum, da cui discendono le risorse post e threads. Se noi volessimo mappare le risorse all&#8217;interno del nosro  sistema, la risorsa &#8216;forum&#8217; sarebbe il controller, &#8216;posts&#8217; e &#8216;threads&#8217; sarebbero le actions.</p>
<p>La parte finale del settaggio dello Zend_Acl riguarda la gestione dei privilegi, che vengono attribuiti tramite lìutilizzo dei metodi allow() e deny() come nel seguente esempio</p>
<pre name="code" class="php">
$acl->allow('utente', 'forum', 'read');
$acl->allow('moderatore', 'forum', array('update', 'blacklist');
</pre>
<p>In questo esempio abbiamo attribuito il permesso di lettura al forum per il gruppo &#8216;utente&#8217; ed inoltre i permessi &#8216;update&#8217; e &#8216;blacklist&#8217; per il gruppo &#8216;moderatore&#8217;. Essendo direttamente discendente dal gruppo &#8216;utente&#8217;, il gruppo &#8216;moderatore&#8217; eredita i permessi del gruppo padre, in modo tale da aver attribuito il permesso di lettura per la risorsa forum.</p>
<h2>Applicazione della teoria</h2>
<p>Il seguente è un esempio dello schema delle tabelle da utilizzare per l&#8217;integrazione pratica di Zend_Acl all&#8217;interno del sistema.</p>
<p><a href='http://razorblade.netsons.org/wp-content/structure.jpg'  class="images"><img src="http://razorblade.netsons.org/wp-content/structure.jpg" alt="Struttura Tabelle Zend_Acl" title="Struttura Tabelle Zend_Acl" width="500" /></a></p>
<p>Niente paura, <a href="http://razorblade.netsons.org/wp-content/acl.txt">qui</a> potete scaricare il file sql contenente il codice per la creazione di queste tabelle con inclusi i record dei roles, della risorsa index_index in lettura ed eliminazione e l&#8217;attribuzione del privilegio lettura per il gruppo superadministrator ( a voi inserire il resto ).</p>
<p>Passiamo ora alla implementazione vera e propria. Prima di tutto dovremo creare una directory all&#8217;interno della directory &#8216;library&#8217; di Zend Framework, questa cartella dovrà avere lo stesso nome del nostro progetto, in questo caso Paesidelmondo. All&#8217;interno di questa directory creiamo un file chiamato Acl.php che conterrà l&#8217;oggetto <b>Paesidelmondo_Acl</b> che estenderà <b>Zend_Acl</b>.</p>
<p><b>Paesidelmondo_Acl</b> si occuperà di inserire i ruoli presenti nel database all&#8217;interno dell&#8217;oggetto <b>Zend_Acl</b>.</p>
<p><b>Acl.php</b></p>
<pre name="code" class="php">
< ?php

  class Paesidelmondo_Acl extends Zend_Acl
  {
    public function __construct() {
      $db = Zend_Registry::get('db');
      $rolesArray = Array();
      $query = "SELECT a.acl_role_name, b.acl_role_name AS acl_role_parent_name FROM
      ( acl_role a LEFT JOIN acl_role b ON a.acl_role_parent_id = b.acl_role_id ) ORDER BY a.acl_role_sort ASC";
      $tbRoleRowset = $db->fetchAll($query);
      foreach($tbRoleRowset AS $k => $v){
        if(!array_key_exists($v["acl_role_name"],$rolesArray)){
          $rolesArray[$v["acl_role_name"]] = Array($v["acl_role_parent_name"]);
        }else{
         array_push($rolesArray[$v["acl_role_name"]],$v["acl_role_parent_name"]);
        }
      }
      $this->_addRoles($rolesArray);
    }

    protected function _addRoles($roles){
      foreach($roles as $name => $parents){
        if (!$this->hasRole($name)){
          $parents = $parents[0] === null ? null : $parents;
          $this->addRole(new Zend_Acl_Role($name), $parents);
        }
      }
    }
  }
</pre>
<p>Il codice di questo oggetto non credo abbia bisogno di molte spiegazioni, segue le regole dette in precedenza sull&#8217;aggiunta dei ruoli all&#8217;interno di <b>Zend_Acl</b>, recuperandoli dal database. Questo oggetto sarà istanziato nel nostro file bootstrap, tramite l&#8217;aggiunta di questa linea di codice:</p>
<pre name="code" class="php">
$acl = new Paesidelmondo_Acl();
</pre>
<p>A questo punto sorge spontanea una domanda: e le risorse? </p>
<p>Per evitare inutili sprechi di memoria e di elaborazioni le risorse non saranno caricate in Zend_Acl nella loro totalità ad ogni nuova chiamata. Invece, le risorse saranno inserite in Zend_Acl tenendo conto del controller e dell&#8217;action richiesta dall&#8217;utente. L&#8217;applicazione di questa teoria può essere svolta tramite la creazione di un <b>action helper</b>.</p>
<p><b>Un Action Helper si inserisce nell&#8217;MVC dispatch system al controller level, permettendoci di accedere alle regole dell&#8217;Acl prima che il metodo preDispatch() del controller sia chiamato. Questo avviene prima della esecuzione della action e quindi è il luogo ideale per effettuare il controllo</b>.<br />
Inoltre possiamo utilizzare sempre il medesimo helper per inserire la risorsa corrente all&#8217;interno di Zend_Acl nonchè abilitare i privilegi per il gruppo a cui appartiene l&#8217;utente corrente.</p>
<p>L&#8217;action controller si chimerà <b>Paesidelmondo_Controller_Action_Helper_Acl</b> ed estenderà <b>Zend_Controller_Action_Helper_Abstract</b></p>
<p>Paesidelmondo/Controller/Action/Helper/<b>Acl.php</b></p>
<pre name="code" class="php">
< ?php

  class Paesidelmondo_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract
  {
    protected $_db;
    protected $_action;
    protected $_auth;
    protected $_acl;
    protected $_controllerName;
    protected $_actionName;
    protected $_resourceName;
    protected $_privileges = Array();
    protected $_roleIds = Array();

    public function __construct(Zend_View_Interface $view = null, array $options = array() ) {
      $this->_auth = Zend_Auth::getInstance();
      $this->_db = Zend_Registry::get('db');
      $this->_acl = $options['acl'];
    }

    public function init(){
      // Ricaviamo controller, action e creiamo il nome risorsa
      $this->_action = $this->getActionController();
      $this->_controllerName = $this->_action->getRequest()->getControllerName();
      $this->_actionName = $this->_action->getRequest()->getActionName();
      $this->_resourceName = $this->_controllerName."_".$this->_actionName;

      // Aggiungiamo la risorsa in Zend_Acl
      // ATTENZIONE: la possibilità di indicare il parent non è stata presa in considerazione!
      if(!$this->_acl->has($this->_resourceName)){
        $this->_acl->add(new Zend_Acl_Resource($this->_resourceName));
      }

      // Ricaviamo il ruolo dell'utente loggato, altrimenti gli attribuiamo 'guest' id = 1
      list($roleId,$userRole) = $this->getUserRole();

      // Aggiungiamo $roleId nell'array che comprenderà anche i suoi id parente
      $this->_roleIds[] = $roleId;

      // Aggiungiamo gli id parente in $this->_roleIds
      $this->fillRoleIds($userRole);

      // Inseriamo i privilegi per l'utente corrente in $this->_privileges
      $this->fillPrivileges($this->_roleIds);

      // Cicliamo l'array ottenuto per inserire i privilegi di questo gruppo per la risorsa corente all'interno di Zend_Acl
      foreach($this->_privileges AS $k => $v){
        $this->$k($userRole,$v);
      }
    }

    public function getUserRole(){
      if($this->_auth->hasIdentity()){
        $user = $this->_auth->getIdentity();
        $roleId = (int)$user->id_gruppo;
        $query = "SELECT acl_role_name FROM acl_role WHERE acl_role_id = '".$roleId."' ";
        $tbRoleRowset = $this->_db->fetchAll($query);
        $userRole = $tbRoleRowset[0]["acl_role_name"];
      }else{
        $roleId = 1;
        $userRole = 'guest';
      }
      return array($roleId,$userRole);
    }

    protected function fillPrivileges($roleIds){
      $roleIds = is_array($roleIds) ? implode(",",$roleIds) : $roleIds;
      $query = "SELECT c.acl_privilege_name AS privilege, c.acl_privilege_type AS type, e.acl_role_parent_id AS parent FROM (((( acl_controller a LEFT JOIN acl_resource b ON a.acl_controller_id = b.acl_controller_id )
                LEFT JOIN acl_privilege c ON b.acl_resource_id = c.acl_resource_id )
                LEFT JOIN acl_role_privilege d ON c.acl_privilege_id = d.acl_privilege_id )
                LEFT JOIN acl_role e ON d.acl_role_id = e.acl_role_id )
                WHERE a.acl_controller_name = '".$this->_controllerName."' AND b.acl_resource_name = '".$this->_actionName."'
                AND e.acl_role_id IN(".$roleIds.") ";
      $privileges = $this->_db->fetchAll($query);
      foreach($privileges AS $k => $v){
        $this->_privileges[$v['type']][] = $v['privilege'];
      }
    }

    protected function fillRoleIds($roleName){
      $query = "SELECT a.acl_role_parent_id, b.acl_role_name FROM acl_role a LEFT JOIN acl_role b ON a.acl_role_parent_id = b.acl_role_id WHERE a.acl_role_name = '".$roleName."' ";
      $parents = $this->_db->fetchAll($query);
      foreach($parents AS $k => $v){
        if(!in_array($v['acl_role_parent_id'],$this->_roleIds)){
          $this->_roleIds[] = $v['acl_role_parent_id'];
        }
        if($v['acl_role_parent_id'] > 0){
          $this->fillRoleIds($v['acl_role_name']);
        }
      }
    }

    public function allow($roles = null, $actions = null) {
      $resource = $this->_resourceName;
      //echo 'allow '.$roles.' to '.implode(',',$actions).' '.$resource.'';
      $this->_acl->allow($roles, $resource, $actions);
      return $this;
    }

    public function deny($roles = null, $actions = null) {
      $resource = $this->_resourceName;
      //echo 'deny '.$roles.' to '.implode(',',$actions).' '.$resource.'';
      $this->_acl->deny($roles, $resource, $actions);
      return $this;
    }

    public function getAcl(){
      return $this->_acl;
    }
  }
</pre>
<p>Il codice è commentato e quindi dovrebbe essere abbastanza comprensibile. L&#8217;unica nota è per il metodo <b>fillRoleIds</b>, che si ricava tutti i parent dell&#8217;attuale gruppo utente in modo da ereditare eventuali privilegi ad essi associati.</p>
<p>Per poter utilizzare questo helper dobbiamo registrarlo. Subito dopo aver creato l&#8217;oggetto acl nel bootstrap aggiungiamo le seguenti 2 righe di codice:</p>
<pre name="code" class="php">
  $aclHelper = new Paesidelmondo_Controller_Action_Helper_Acl(null, array('acl'=> $acl));
  Zend_Controller_Action_HelperBroker::addHelper($aclHelper);
</pre>
<p>Infine non ci manca che modificare il metodo init dei controller in cui vogliamo effettuare il controllo dei permessi. Il seguente è il codice del metodo init() dell&#8217;indexController:</p>
<pre name="code" class="php">
    public function init(){
      $response = $this->getResponse();
      $response->insert('header', $this->view->render('header.phtml'));
      $response->insert('menu', $this->view->render('menu.phtml'));
      $response->insert('columnLeft', $this->view->render('columnLeft.phtml'));
      $response->insert('columnRight', $this->view->render('columnRight.phtml'));
      $response->insert('footer', $this->view->render('footer.phtml')); 

      $request = $this->getRequest();
      $resourceName = $request->getControllerName().'_'.$request->getActionName();

      $errorMessage = "";
      $acl = $this->_helper->_acl->getAcl();
      list($roleId,$userRole) = $this->_helper->_acl->getUserRole();
      $readPrivilege = $acl->isAllowed($userRole, $resourceName, 'read');

      if(!$acl->hasRole($userRole)){
        $errorMessage.= "

Il ruolo utente non esiste, permesso negato

";
      }
      if(!$readPrivilege){
        $errorMessage.= "

ERRORE: Accesso Negato

";
      }
      /*
      if(!$acl->has($resourceName)){
        $errorMessage.= "

La risorsa ".str_replace("_","/",$resourceName). "non esiste!

";
      }
      */

      if(!empty($errorMessage)){
        Zend_Layout::getMvcInstance()->getView()->errorMessage = $errorMessage;
        $request->setControllerName('error');
        $request->setDispatched(false);
      }
    }
</pre>
<p>In questo caso abbiamo verificato se il gruppo dell&#8217;attuale utente possiede i permessi in lettura per la risorsa. Nel database non abbiamo attribuito questo permesso a nessun ruolo, quindi inevitabilmente saremo redirezionati all&#8217;errorController che visualizzerà il messaggio di errore ( se non lo avete, create il file index.phtml negli script della vista relativi all&#8217;errorController ).</p>
<p>Come potete notare abbiamo utilizzato 2 metodi mai visti prima d&#8217;ora di Zend_Acl: hasRole e has. Il primo controlla se il gruppo utente è realmente esistente ( quindi se è stato inserito in Zend_Acl quando questo è stato istanziato OVVERO se è presente nel database ), mentre il secondo controlla se la risorsa è effettivamente presente. In questo caso ho commentato quella porzione di codice in quanto il nostro acl helper attualmente aggiunge la risorsa senza controllare della sua esistenza nel database. Questo perchè non sarebbe di utilità, infatti se la risorsa non esistesse non arriveremo mai a eseguire quel codice ma il sistema ci avvertirebbe della non presenza dello script ( ma solo alla situazione attuale, in cui abbiamo settato $frontController->throwExceptions(true); nel nostro bootstrap ). Vedremo prossimamente come reindirizzare eventuali chiamate a controller non esistenti.</p>
<p>Con questo si conclude questo tutorial, che non voleva spiegare l&#8217;implementazione definitiva di Zend_Acl per ogni caso, ma solo una possibile sua implementazione ( funzionante ). Alcune cose sono state volutamente tralasciate, come l&#8217;ereditarietà tra risorse o la creazione dei modelli per le nuove tabelle del database. Per eventuali domande, dimenticanze o suggerimenti il consiglio è sempre quello di scrivere qui sotto.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/09/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-9/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Costruire un’applicazione reale con Zend Framework ( parte 7 )</title>
		<link>http://razorblade.netsons.org/2008/08/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-7/</link>
		<comments>http://razorblade.netsons.org/2008/08/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-7/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 03:32:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[$_dependentTables]]></category>
		<category><![CDATA[$_name]]></category>
		<category><![CDATA[$_referenceMap]]></category>
		<category><![CDATA[$_rowClass]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[findManyToManyRowset]]></category>
		<category><![CDATA[molti a molti]]></category>
		<category><![CDATA[uno a molti]]></category>
		<category><![CDATA[zend fetchRow]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=30</guid>
		<description><![CDATA[<h2>$_name, $_referenceMap e $_dependentTables</h2>
<p>Nel codice che componeva le classi per la gestione delle tabelle del nostro database avrete notato la presenza delle proprietà <b>$_name</b>, <b>$_referenceMap</b> e <b>$_dependentTables</b>.
Vediamole nel <a href="http://razorblade.netsons.org/2008/08/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-7/">[...] Continua</a></p>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>$_name, $_referenceMap e $_dependentTables</h2>
<p>Nel codice che componeva le classi per la gestione delle tabelle del nostro database avrete notato la presenza delle proprietà <b>$_name</b>, <b>$_referenceMap</b> e <b>$_dependentTables</b>.<br />
Vediamole nel dettaglio</p>
<p>La proprietà <b>$_name</b> serve a salvare internamente ad una classe il nome della tabella a cui questa è relazionata. Infatti, in caso di omissione di questa proprietà, il sistema andrebbe a cercare una tabella con lo stesso nome della classe, preservando le lettere maiuscole/minuscole. Per fare un esempio, se $_name fosse omessa nella classe Utenti, la tabella Utenti sarebbe ricercata dal sistema e questo genererebbe un errore. Siccome per convenzione nominiamo le nostre classi con la prima lettera maiuscola , la proprietà $_name ci viene incontro per salvare il nome corretto della tabella.</p>
</p>
<p>Vediamo adesso il codice della classe Recensioni. Questa classe è l&#8217;unica a contenere la proprietà $_referenceMap. Questa proprietà è un array che serve ad indicare <b>a quale classe relazionare le foreign keys presente nella tabella in questione</b> e nel nostro caso, la tabella recensioni è l&#8217;unica a contenere foreign keys. Le chiavi di questo array conterranno il nome della relazione ( rules ) ed il loro valore sarà un array contenente la foreign key, il nome della classe a cui la relazione si riferisce ed il nome della colonna di relazione, rispettivamente columns, refTableClass e refColumns.</p>
<p><b>$_referenceMap in Recensioni</b></p>
<pre name="code" class="php">
    protected $_referenceMap = array(
      'Paesi' => array(
        'columns'           => array('id_paese'),
        'refTableClass'     => 'Paesi',
        'refColumns'        => array('id')
      ),
      'Utenti' => array(
        'columns'           => array('id_utente'),
        'refTableClass'     => 'Utenti',
        'refColumns'        => array('id')
      ) ,
      'Abilitazione' => array(
        'columns'           => array('id_utente_abilitazione'),
        'refTableClass'     => 'Utenti',
        'refColumns'        => array('id')
      )
    );
</pre>
<p>Infine <b>$_dependentTables</b> è un array che definisce la o le classi ( tabelle ) direttamente dipendenti. Nel caso di Utenti e Paesi il valore di $_dependentTables è un array contenente Recensioni</p>
<h2>Esempi di utilizzo</h2>
<p>Inseriamo quindi qualche esempio nel nostro IndexController, il seguente codice è un esempio di accesso ai dati del database al <b>row level</b></p>
<p><pre name="code" class="php">
$utenti = new Utenti;
$myself = $utenti->fetchRow('id = 1');
$this->view->myself = $myself->name;
</pre>
<p>Il metodo fetchRow() ritorna una istanza della classe Utente, mentre name richiama l&#8217;omonimo metodo, la possibilità di effettuare una chiamata ad un metodo come se si trattasse di una proprietà l&#8217;abbiamo aggiunta tramite l&#8217;overload del metodo magico __get() ( ricordate? ne abbiamo parlato lo scorso articolo ). Per visualizzare la variabile ottenuta aggiungeremo in index.phtml la seguente linea</p>
<pre name="code" class="php">
&lt;p&gt;Utente ID 1: &lt;?php echo $this->myself;?&gt; &lt;/p&gt;
</pre>
<h3>Il metodo findDependentRowset</h3>
<p>Questo metodo serve per effettuare una relazione <b>uno a molti</b> ed utilizza le proprietà $_referenceMap e $_dependentTables. Di seguito un esempio di utilizzo</p>
<pre name="code" class="php">
$paesi = new Paesi;
$paese= $paesi->fetchRow('id = 1');
$resOne = $paese->findDependentRowset( 'Recensioni');
</pre>
<h3>Il metodo findManyToManyRowset</h3>
<p>Questo metodo serve per effettuare una relazione <b>molti a molti</b> ed utilizza anch&#8217;esso le proprietà $_referenceMap e $_dependentTables di cui abbiamo parlato. Il primo argomento è la tabella di destinazione, metre il secondo argomento è la tabella di incrocio.</p>
<p><pre name="code" class="php">
$utenti = new Utenti;
$myself = $utenti->fetchRow('id = 1');
$resOne = $myself->findManyToManyRowset( 'Paesi','Recensioni');
</pre>
</p>
<p>Il rowset risultante sarà composto da tutti i campi della tabella recensioni e da tutti i campi della tabella paesi, le righe selezionate ovviamente saranno quelle dove id_utente in recensioni è = a 1 ( l&#8217;utente selezionato da fetchRow() ). Questo metodo accetta eventuali regole definite in $_referenceMap. Infatti, in caso volessimo selezionare non le recensioni scritte dall&#8217;id 1 ma bensi le recensioni abilitate dall&#8217;utente id 1, il codice sarebbe il seguente</p>
<p><pre name="code" class="php">
$utenti = new Utenti;
$myself = $utenti->fetchRow('id = 1');
$resOne = $myself->findManyToManyRowset( 'Paesi','Recensioni','Abilitazione');
</pre>
</p>
<p>Testate entrambe i casi eventualmente aggiungendo degli altri record al vostro database. Questo è il codice da inserire in index.phtml</p>
<pre name="code" class="php">
&lt;?php if(count($this-&gt;resOne)): ?&gt;
&lt;table&gt;
&lt;tr&gt;
  &lt;td&gt;Id&lt;/td&gt;
  &lt;td&gt;Nome&lt;/td&gt;
  &lt;td&gt;Descrizione&lt;/td&gt;
&lt;/tr&gt;
&lt;?php foreach($this-&gt;resOne as $p): ?&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;?php  echo $p-&gt;id; ?&gt;&lt;/td&gt;
  &lt;td&gt;&lt;?php  echo $p-&gt;nome; ?&gt;&lt;/td&gt;
  &lt;td&gt;&lt;?php echo $p-&gt;descrizione; ?&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;?php endforeach;?&gt;
&lt;/table&gt;
&lt;?php endif;?&gt;
</pre>
<p>Si conclude così questa settima parte. Per ogni dubbio siete invitati ad utilizzare la funzionalità commento al termine di ogni articolo</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/08/19/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Costruire un’applicazione reale con Zend Framework ( parte 6 )</title>
		<link>http://razorblade.netsons.org/2008/08/18/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-6/</link>
		<comments>http://razorblade.netsons.org/2008/08/18/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-6/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 02:50:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[$_dependentTables]]></category>
		<category><![CDATA[$_referenceMap]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[gestione database con zend framework]]></category>
		<category><![CDATA[insert]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[Zend_Db_Adapter]]></category>
		<category><![CDATA[Zend_Db_Table]]></category>
		<category><![CDATA[Zend_Db_Table_Abstract]]></category>
		<category><![CDATA[Zend_Db_Table_Row_Abstract]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=29</guid>
		<description><![CDATA[<h2>Gestione del database</h2>
<p>Ritorniamo sull'argomento modelli iniziato qualche articolo fa, in questo articolo tratteremo come recuperare i dati dal database con <b>Zend Framework</b>. Una volta creato l'oggetto $db tramite chiamata al metodo statico factory, potremo procedere in <a href="http://razorblade.netsons.org/2008/08/18/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-6/">[...] Continua</a></p>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Gestione del database</h2>
<p>Ritorniamo sull&#8217;argomento modelli iniziato qualche articolo fa, in questo articolo tratteremo come recuperare i dati dal database con <b>Zend Framework</b>. Una volta creato l&#8217;oggetto $db tramite chiamata al metodo statico factory, potremo procedere in diversi modi.</p>
<h2>Effettuare una query</h2>
<p>Tramitel&#8217;utilizzo del metodo &#8216;query&#8217; potremo eseguire direttamente la query da noi specificata sul database, ad esempio:</p>
<pre name="code" class="php">
$data = $db->quote('1990-01-01');
$sql = 'SELECT * FROM utenti WHERE data_di_nascita > ' . $date;
$result = $db->query($sql);
</pre>
<p>Nel codice precedente abbiamo utilizzato il metodo &#8216;quote&#8217; che effettua per noi l&#8217;inserimento degli apici in modo da creare una query corretta ed esente da pericoli di SqlInjections.<br />
Tuttavia potrebbe capitare di dimenticare di usare quote quindi l&#8217;ideale potrebbe essere utilizzare il seguente metodo per scrivere una query corretta e sicura:</p>
<pre name="code" class="php">
$sql = 'SELECT * FROM utenti WHERE data_di_nascita > ?'
$result = $db->query($sql, array('1990-01-01'));
</pre>
<p>In ogni caso, il $result sarà un oggetto su cui potremo effettuare le chiamate dei metodi fetch() e fetchAll() per il recupero dei dati.</p>
<h2>Zend_Db_Select</h2>
<p>Zend_Db_Select è un oggetto che ci viene in aiuto per costruire delle query per la selezione di dati utilizzando maggiormente il linguaggio php piuttosto che SQL. Prendendo in considerazione l&#8217;esempio precedente, il codice qui di seguito mostra come ottenere lo stesso risultato utilizzando questa classe:</p>
<pre name="code" class="php">
$select = new Zend_Db_Select($db);
$select->from('utenti');
$select->where('data_di_nascita > ?', '1990-01-01');
$result = $select->query();
</pre>
<h2>Inserimento, Modifica ed Eliminazione dei dati con Zend_Db_Adapter</h2>
<p>Per effettuare queste operazioni, la classe Zend_Db_Adapter ci offre i metodi insert(), update() e delete() rispettivamente. Il loro utilizzo è decisamente semplice, creare un array associatico con chiave  il nome del campo della nostra tabella e come valore appunto il valore che dovrà avere questo campo, e passarlo ai vari metodi sopra citati nei seguenti modi:</p>
<p><b>inserimento</b></p>
<pre name="code" class="php">
  $data = array(,
    'nome' => 'Mark',
    'cognome' => 'Hollis',
    'inserimento_data' => date('Y-m-d')
  ); 

  $table = 'utenti';
  $rows_affected = $db->insert($table, $data);
  $last_insert_id = $db->lastInsertId();
</pre>
<p><b>modifica</b></p>
<pre name="code" class="php">
  $data = array(,
    'paese' => 'United Kingdom'
  ); 

  $table = 'utenti';
  $where = $db->quoteInto('country = ?', 'UK');
  $db->update($table, $data, $where);
</pre>
<p><b>elimina</b></p>
<pre name="code" class="php">
  $table = 'utenti';
  $where = 'id = 2';
  $rows_affected = $db->delete($table, $where);
</pre>
<h2>Inserimento, Modifica ed Eliminazione dei dati con Zend_Db_Table</h2>
<p>Un&#8217;interessante metodo per la gestione del database ci viene offerto dalla classe Zend_Db_Table. Questa classe gestisce ogni tabella del database come se fosse un oggetto. Prima di cominciare con gli esempi aggiungiamo una nuova tabella al nostro database</p>
<pre name="code" class="php">
CREATE TABLE `utenti` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(99) NOT NULL,
  `password` varchar(32) NOT NULL,
  `nome` varchar(99) NOT NULL,
  `cognome` varchar(99) NOT NULL,
  `sesso` enum('M','F') default NULL,
  `data_di_nascita` datetime NOT NULL,
  `paese` varchar(99) default NULL,
  `cap` varchar(20) NOT NULL,
  `inserimento_data` datetime NOT NULL,
  `inserimento_user_id` int(11) NOT NULL,
  `inserimento_ip` varchar(15) NOT NULL,
  `modifica_data` timestamp NULL default NULL on update CURRENT_TIMESTAMP,
  `modifica_user_id` int(11) default NULL,
  `modifica_ip` varchar(15) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

INSERT INTO `utenti` (`id`, `username`, `password`, `nome`, `cognome`, `sesso`, `data_di_nascita`, `paese`, `cap`, `inserimento_data`, `inserimento_user_id`, `inserimento_ip`, `modifica_data`, `modifica_user_id`, `modifica_ip`) VALUES
(1, 'Razorblade', '0c88028bf3aa6a6a143ed846f2be1ea4', 'Sergio', 'Rinaudo', 'M', '1982-03-26 20:56:22', NULL, '10023', '2008-08-16 20:56:51', 1, '127.0.0.1', '2008-08-16 20:57:01', NULL, NULL);
</pre>
<p>Abbiamo dunque creato la tabella utenti, quindi possiamo procedere alla creazione della relativa classe. Questo nuovo file andrà salvato nella directory models</p>
<p><b>Utenti.php</b></p>
<pre name="code" class="php">
&lt;?php

  class Utenti extends Zend_Db_Table_Abstract
  {
    protected $_name = 'utenti';
    protected $_rowClass = 'Utente';
    protected $_dependentTables = array('Recensioni');
  }
</pre>
<p>In quanto Utenti estende Zend_Db_Table_Abstract come potete immaginare ne eredita i vari metodi e proprietà. Prima di procedere alla spiegazione di cosa siano le proprietà presenti all&#8217;interno della classe Utenti diamo uno sguardo su come effettuare le medesime operazioni di inserimento, modifica e update utilizzando Zend_Db_Table_Abstract</p>
<p><b>inserimento</b></p>
<pre name="code" class="php">
  $utenti = new Utenti(); 

  $data = array(,
    'nome' => 'Mark',
    'cognome' => 'Hollis',
    'inserimento_data' => date('Y-m-d')
  ); 

  $id = $utenti->insert($data);
</pre>
<p><b>modifica</b></p>
<pre name="code" class="php">
  $utenti = new Utenti(); 

  $data = array(,
    'paese' => 'United Kingdom'
  ); 

  $where = $db->quoteInto('country = ?', 'UK');
  $utenti->update($data, $where);
</pre>
<p><b>elimina</b></p>
<pre name="code" class="php">
  $utenti = new Utenti(); 

  $where = 'id = 2';
  $utenti->delete($where);
</pre>
<h2>Creazione dei nuovi modelli per l&#8217;applicazione</h2>
<p>Prima di listare il codice delle classi delle altre tabelle del nostro database, ovvero recensioni e paesi, dobbiamo fare una precisazione sui livelli di accesso al database, che possono essere di due tipi: tabella e riga. Il primo livello di accesso è utlizzato quando dobbiamo creare dei listati di record, il secondo livello è utilizzato quando abbiamo a che fare con un singolo record della tabella. </p>
<p>Lavorando al secondo livello di accesso è inoltre possibile utilizzare il metodo save() in sostituzione di insert e update, il codice per effettuare entrambe le operazioni è molto simile:</p>
<p><b>inserimento</b></p>
<pre name="code" class="php">
  $utenti = new Utenti();
  $riga = $utenti->fetchNew(); 

  $riga->nome = 'Mark';
  $riga->cognome = 'Hollis'; 

  $riga->save();
</pre>
<p><b>modifica</b></p>
<pre name="code" class="php">
  $utenti = new Utenti();
  $riga = $utenti->fetchRow('id=2'); 

  $riga->nome = 'Mark';
  $riga->cognome = 'Hollis'; 

  $riga->save();
</pre>
<p>La classe Utenti da noi creata poco sopra agisce a livello di tabella. Al suo interno si trova una proprietà, $_rowClass, che indica il nome della classe per la gestione del secondo livello di accesso, ovvero Utente. Il seguente è il codice che ha attualmente Utente:</p>
<pre name="code" class="php">
&lt;?php

  class Utente extends Zend_Db_Table_Row_Abstract
  {
    public function name(){
      $name = trim($this->nome . ' ' . $this->cognome);
      if (empty($name)) {
        $name = $this->username;
      }
      return $name;
    }

    function __get($key)
    {
      if(method_exists($this, $key)){
        return $this->$key();
      }
      return parent::__get($key);
    }
  }
</pre>
<p>Come avrete sicuramente notato, il primo livello di accesso è gestito dalla classe <b>Zend_Db_Table_Abstract </b> mentre il secondo è gestito da <b>Zend_Db_Table_Row_Abstract </b>. Nella classe Utente abbiamo inserito due metodi, il primo serve a ricavare il nome dell&#8217;utente selezionato, il secondo è un metodo magico ( presto disponibile un articolo sui metodi magici su questo blog, fino ad allora vi consiglio una ricerca su google per saperne di più ) che ci da la possibilità di richiamare il metodo name come se fosse una proprietà ( omettendo le parentesi ).</p>
<p>Di seguito trovate il codice attuale delle classi Paesi e Recensioni, da inserire all&#8217;interno della directory models, assieme ad Utenti e Utente</p>
<p><b>Paesi</b></p>
<pre name="code" class="php">
&lt;?php

  class Paesi extends Zend_Db_Table
  {
    protected $_name = 'paesi';
    protected $_dependentTables = array('Recensioni');

    function fetchLatest($count = 10){
      return $this->fetchAll(null,'inserimento_data DESC', $count);
    }
  }
</pre>
<p><b>Recensioni</b></p>
<pre name="code" class="php">
&lt;?php 

  class Recensioni extends Zend_Db_Table_Abstract
  {
    protected $_name = 'recensioni';
    protected $_referenceMap = array(
      'Paesi' => array(
        'columns'           => array('id_paese'),
        'refTableClass'     => 'Paesi',
        'refColumns'        => array('id')
      ),
      'Utenti' => array(
        'columns'           => array('id_utente'),
        'refTableClass'     => 'Utenti',
        'refColumns'        => array('id')
      ) ,
      'Abilitazione' => array(
        'columns'           => array('id_utente_abilitazione'),
        'refTableClass'     => 'Utenti',
        'refColumns'        => array('id')
      )
    );
  }
</pre>
<p>Nel prossimo articolo continueremo il discorso sui modelli, spiegando nel dettaglio a cosa servono le proprietà $_referenceMap e $_dependentTables ed effettueremo dei test di visualizzazione.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/08/18/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-6/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Costruire un’applicazione reale con Zend Framework ( parte 5 )</title>
		<link>http://razorblade.netsons.org/2008/08/15/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-5/</link>
		<comments>http://razorblade.netsons.org/2008/08/15/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-5/#comments</comments>
		<pubDate>Fri, 15 Aug 2008 15:30:46 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Ajax con Zend Framework]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[AsyncRequestController]]></category>
		<category><![CDATA[indexAction]]></category>
		<category><![CDATA[IndexController]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[prototype]]></category>
		<category><![CDATA[scriptaculous]]></category>
		<category><![CDATA[YUI library]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=28</guid>
		<description><![CDATA[<h2>Ajax con Zend Framework</h2>
<p>Premetto che il seguente è solo uno dei possibili metodi di usare <b>ajax</b> all'interno della vostra applicazione sviluppata con <b>Zend Framework</b>, ma sicuramente è il metodo che più mantiene il concetto di MVC. In questo articolo <a href="http://razorblade.netsons.org/2008/08/15/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-5/">[...] Continua</a></p>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Ajax con Zend Framework</h2>
<p>Premetto che il seguente è solo uno dei possibili metodi di usare <b>ajax</b> all&#8217;interno della vostra applicazione sviluppata con <b>Zend Framework</b>, ma sicuramente è il metodo che più mantiene il concetto di MVC. In questo articolo integreremo le richieste asincrone tramite l&#8217;uso di un framework javascript. Tra i vari framework javascript esistenti quello che personalmente preferisco è <b>JQuery</b> ed è quindi quello che utilizzerò in questo articolo. Purtroppo ad oggi non ho ancora scritto nessun articolo su questo fantastico framework, quindi se volete saperne di più o volete vedere subito qualche esempio non vi rimane che cercare su internet.</p>
<p>Giusto per completezza, esistono diversi altri framework javascript che gestiscono le richieste asincrone, tra cui <b>Prototype</b>, <b>Script.aculo.us</b>, <b>YUI library di Yahoo!</b> e diversi altri.</p>
<h2>Recuperare JQuery</h2>
<p>Potete scaricare l&#8217;ultima versione di <b>JQuery</b> dal sito ufficiale <a href="http://www.jquery.com/" title="JQuery">jquery.com/</a>. Una volta scaricato il file questo dev&#8217;essere inserito nella cartella js presente nella web root del nostro progetto.</p>
<h2>Layout.phtml</h2>
<p>Il primo passo sarà l&#8217;aggiunta del framework javascript all&#8217;interno dell&#8217;applicazione. Per fare ciò aggiungeremo due righe di codice nel nostro file layout.phtml, che vi ricordo si trova all&#8217;interno di application\views\layouts</p>
<pre name="code" class="php">
    &lt;script type="text/javascript" src="&lt;?php echo $this->baseUrl(); ?&gt;/js/jquery.js" /&gt;
    &lt;script type="text/javascript" src="&lt;?php echo $this->baseUrl(); ?&gt;/js/ajax.js" /&gt;
</pre>
<h2>Header.phtml</h2>
</p>
<p>Il prossimo file a subire modifiche sarà header.phtml. In questo file andremo ad aggiungere un breve form con un input di testo dove poter inserire il nome utente.</p>
<pre name="code" class="php">
&lt;h1&gt;Paesidelmondo Header&lt;/h1&gt;

&lt;form action="#"&gt;
 &lt;fieldset&gt;
  &lt;legend&gt;Registratione&lt;/legend&gt;
  &lt;label for="name"&gt;Nome Utente:&lt;/label&gt;&lt;input id="name" name="name" type="text" autocomplete="off" /&gt;
 &lt;/fieldset&gt;
&lt;/form&gt;
&lt;div id="message"&gt;&lt;/div&gt;
</pre>
<h2>Ajax.js</h2>
<p>Creiamo un file e chiamiamolo per comodità ajax.js. Questo conterrà il codice javascript che <b>metterà in ascolto l&#8217;input di testo con l&#8217;evento keyup</b> e che gestirà la richiesta asincrona, codice che ovviamente utilizza il framework JQuery che abbiamo aggiunto poco fa. Questo file è da salvare all&#8217;interno della cartella js. Il seguente è il codice.</p>
<pre name="code" class="php">
  $(document).ready(function(){
    $("#name").bind('keyup',function(){
      var baseUrl = "http://localhost";
      var nome = $(this).val();
      var destUrl = baseUrl + "/asyncrequest/username/nome/" + nome;
      $.ajax({
        url: destUrl,
        type: 'GET',
        success:  function(responseText){
          $("#message").html(responseText);
        }
      });
    });
  });
</pre>
<p>Come potete notare voi stessi all&#8217;interno del codice è presente la stringa &#8216;/asyncrequest/username/nome/&#8217;, questo significa che nella nostra applicazione è presente un nuovo controller, asyncrequest che contiene una action chiamata username.</p>
<h2>AsyncRequestController.php</h2>
<p>Creiamo un nuovo file controller e chiamiamolo AsyncRequestController.php, che salveremo nella directory dei controllers, application\controllers. Il seguente sarà il suo contenuto</p>
<pre name="code" class="php">
&lt;?php
  class AsyncRequestController extends Zend_Controller_Action {

    public function usernameAction(){
      $utenti = array('zend', 'jquery', 'javascript');
      $username = $this->_request->getParam('nome');
      if ($username == ''){
        $return = '';
      }elseif (strlen($username) < 4){
        $return = '
<p class="error">Nome Utente troppo corto!';
      }elseif (in_array($username, $utenti)){
        $return = '
<p class="error">Utente gi&agrave; esistente

';
      }else{
        $return = '
<p class="ok">Nome Utente Valido

';
      }
      $this->_response->appendBody($return);
      $this->_helper->layout->disableLayout();
    }

  }
</pre>
<p>Principalmente sono 2 i punti degni di nota in questo codice, $this->_response->appendBody($return);  che inserisce nell&#8217;output il contenuto ritornato e $this->_helper->layout->disableLayout(); che disabilita il layout. Questo è indispensabile in quanto non vogliamo che ad ogni richiesta asincrona il sistema ci restituisca anche il layout.</p>
<p>Procediamo quindi con la creazione della view per la action che abbiamo appena creato, ovvero username.phtml.</p>
<h2>username.phtml</h2>
<p>Come abbiamo creato la directory <b>index</b></p>
<p> all&#8217;interno della directory views\scripts per la gestione delle action dell&#8217;<b>IndexController</b>, procederemo a creare la directory <b>asyncRequest</b> nella stessa locazione, per la gestione delle views delle relative action.<br />
La action username.phtml dovrà semplicemente visualizzare il contenuto di result, quindi il suo codice sarà semplicemente
<pre name="code" class="php">
&lt;?php echo $this->result; ?&gt;
</pre>
</p>
<h2>main.css</h2>
<p>Per concludere aggiungiamo una piccola porzione di codice nel nostro css per la gestione di due nuove classi che abbiamo appena inserito all&#8217;interno di ajax.js</p>
<pre name="code" class="php">

	/**************************************************************************
	* Stili Generici
	**/

	.ok {
		color: green;
	}

    .error {
		color: red;
	}
</pre>
<p>Se avete eseguito correttamente ogni passaggio potrete amirare nel vostro header un form che vi restituirà un messaggio man mano che inserite dei caratteri all&#8217;interno dell&#8217;input di testo presente!</p>
<p>Termina così la quinta parte sullo sviluppo di una vera applicazione con zend framework, se qualcuno di voi ha domande può inviare un commento al termine di ogni articolo.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/08/15/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Costruire un’applicazione reale con Zend Framework ( parte 4 )</title>
		<link>http://razorblade.netsons.org/2008/08/08/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-4/</link>
		<comments>http://razorblade.netsons.org/2008/08/08/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-4/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 09:02:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[DisplayDate]]></category>
		<category><![CDATA[indexAction]]></category>
		<category><![CDATA[IndexController]]></category>
		<category><![CDATA[PDO MySql]]></category>
		<category><![CDATA[view helper]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=27</guid>
		<description><![CDATA[<h2>I Modelli</h2>

Eccoci giunti alla realizzazione del nostro primo modello. 
Se non l'avete ancora fatto, dovrete creare il database <b>paesidelmondo</b> in cui andrete a creare 2 tabelle ed inserire alcuni dati. Niente paura, basta far eseguire la seguente query al vostro db e tutto sarà pronto per cominciare <a href="http://razorblade.netsons.org/2008/08/08/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-4/">[...] Continua</a>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>I Modelli</h2>
<p>Eccoci giunti alla realizzazione del nostro primo modello.<br />
Se non l&#8217;avete ancora fatto, dovrete creare il database <b>paesidelmondo</b> in cui andrete a creare 2 tabelle ed inserire alcuni dati. Niente paura, basta far eseguire la seguente query al vostro db e tutto sarà pronto per cominciare:</p>
<pre name="code" class="php">
CREATE TABLE `paesi` (
  `id` int(11) NOT NULL auto_increment,
  `nome` varchar(99) NOT NULL,
  `provincia` varchar(99) NOT NULL,
  `inserimento_data` datetime NOT NULL,
  `inserimento_user_id` int(11) NOT NULL,
  `inserimento_ip` varchar(15) NOT NULL,
  `modifica_data` timestamp NULL default NULL on update CURRENT_TIMESTAMP,
  `modifica_user_id` varchar(11) default NULL,
  `modifica_ip` varchar(15) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Dump dei dati per la tabella `paesi`
-- 

INSERT INTO `paesi` (`id`, `nome`, `provincia`, `inserimento_data`, `inserimento_user_id`, `inserimento_ip`, `modifica_data`, `modifica_user_id`, `modifica_ip`) VALUES
(1, 'Chieri', 'Torino', '2008-08-06 17:26:05', 1, '127.0.0.1', '2008-08-06 17:26:41', NULL, NULL),
(2, 'Pessione', 'Torino', '2008-08-06 17:26:32', 1, '127.0.0.1', '2008-08-06 17:26:41', NULL, NULL);

-- --------------------------------------------------------

--
-- Struttura della tabella `recensioni`
-- 

CREATE TABLE `recensioni` (
  `id` int(11) NOT NULL auto_increment,
  `id_paesi` int(11) NOT NULL,
  `descrizione` mediumtext NOT NULL,
  `inserimento_data` datetime NOT NULL,
  `inserimento_user_id` int(11) NOT NULL,
  `inserimento_ip` varchar(15) NOT NULL,
  `modifica_data` timestamp NOT NULL default '0000-00-00 00:00:00' on update CURRENT_TIMESTAMP,
  `modifica_user_id` int(11) default NULL,
  `modifica_ip` varchar(15) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Dump dei dati per la tabella `recensioni`
-- 

INSERT INTO `recensioni` (`id`, `id_paesi`, `descrizione`, `inserimento_data`, `inserimento_user_id`, `inserimento_ip`, `modifica_data`, `modifica_user_id`, `modifica_ip`) VALUES
(1, 1, '

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river named Duden flows by their place and supplies it with the necessary regelialia.

\r\n\r\n

 It is a paradisematic country, in which roasted parts of sentences fly into your mouth. Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.

\r\n\r\n

 The Big Oxmox advised her not to do so, because there were thousands of bad Commas, wild Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. She packed her seven versalia, put her initial into the belt and made herself on the way. When she reached the first hills of the Italic Mountains, she had a last view back on the skyline of her hometown Bookmarksgrove, the headline of Alphabet Village and the subline of her own road, the Line Lane. Pityful a rethoric question ran over her cheek, then 

', '2008-08-06 17:27:44', 1, '127.0.0.1', '0000-00-00 00:00:00', NULL, NULL),
(2, 2, '

 Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores.

\r\n\r\n

 At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues.

\r\n\r\n

 It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es. Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. 

', '2008-08-06 17:28:21', 1, '127.0.0.1', '0000-00-00 00:00:00', NULL, NULL);
</pre>
<h2>Il primo modello</h2>
<p>Il primo modello che andremo ad implementare recupererà i dati all&#8217;interno della tabella &#8216;paesi&#8217;. Il file, chiamato <b>Paesi.php</b> deve essere creato all&#8217;interno di application\models. Il seguente è il suo contenuto:</p>
<pre name="code" class="php">
< ?php

  class Paesi extends Zend_Db_Table
  {
    function fetchLatest($count = 10) {
      return $this->fetchAll(null,'inserimento_data DESC', $count);
    }
  }
</pre>
<p>Per fare in modo che tutto funzioni, il motore php sul nostro server dovrà avere caricato le estensioni php_pdo e php_pdo_mysql, in quanto, per questa applicazione, abbiamo specificato l&#8217;utilizzo del driver pdo nel file di configurazione config.ini.</p>
<h2>Il metodo fetchAll</h2>
<p>Il metodo fetchAll recupera tutte le righe e tutte le colonne di un resultset. Sintassi:</p>
<pre name="code" class="php">
fetchAll($where, $order, $count, $offset);
</pre>
<p>Nel nostro esempio abbiamo inserito questo metodo all&#8217;interno di fetchLatest, nome che abbiamo dato ad un metodo che recupera gli ultimi X record inseriti ( 10 di default ).</p>
<h2>IndexController</h2>
<p>Modifichiamo quindi la indexAction del nostro IndexController.</p>
<pre name="code" class="php">
    public function indexAction(){
      $this->view->pageTitle = 'Paesidelmondo Application Example';
      $this->view->bodyTitle = 'Paesidelmondo';
      $paesi = new Paesi();
      $this->view->paesi = $paesi->fetchLatest();
    }
</pre>
<p>In questo modo creiamo la variabile <b>paesi</b> all&#8217;interno della view ( $this->view->paesi ), contenente un array di oggetti che potremo ciclare nel nostro index.phtml.</p>
<h2>Index.phtml</h2>
<p>Il seguente è il nuovo contenuto di index.html</p>
<pre name="code" class="php">
&lt;h2&gt;&lt; ?php echo $this-&gt;escape($this-&gt;bodyTitle);?&gt;&lt;/h2&gt;
&lt; ?php // echo $this-&gt;bodyContent;?&gt;

&lt; ?php if(count($this-&gt;paesi)): ?&gt;
&lt;table&gt;
&lt; ?php foreach($this-&gt;paesi as $paese): ?&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;a href="&lt;?php echo $this-&gt;baseUrl;?&gt;/paese/&lt; ?php
    echo $paese-&gt;id; ?&gt;"&gt;&lt; ?php
    echo $this-&gt;escape($paese-&gt;nome); ?&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;td&gt;&lt; ?php echo $this-&gt;displayDate($paese-&gt;modifica_data); ?&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt; ?php endforeach;?&gt;
&lt;/table&gt;
&lt; ?php endif;?&gt;
</pre>
<p>Per comodità ho eliminato dalla visualizzazione il contenuto di bodyContent in modo da concentrarci meglio sui dati estrapolati dal database.<br />
Il codice credo che sia autoesplicativo, l&#8217;unica nota da fare è sul metodo <b>displayDate</b>, metodo facente parte di un nuovo helper, DisplayDate.php da inserire all&#8217;interno di application\views\helpers</p>
<h2>Display date</h2>
<p>Il seguente è il codice di DisplyDate.php</p>
<pre name="code" class="php">
< ?php

  class Zend_View_Helper_DisplayDate {
    function displayDate($time, $format='%d %B %Y'){
      $timestamp = strtotime($time);
      return strftime($format, $timestamp);
    }
  }
</pre>
<p>Questo metodo trasforma le date ritornate dal db in una data più facilmente leggibile.<br />
Infine, prima di poter testare il tutto, aggiungiamo una semplice linea di codice al nostro bootstrap index.php, ovvero una nuova include_path, quella per i modelli.
</pre>
<pre name="code" class="php">
  // Blocco 1
  [ ... ]

  // Blocco 1b
  set_include_path(ZEND_ROOT.'application/models'.PATH_SEPARATOR.get_include_path());

  [ ... ]
</pre>
<p>Non ci rimane che testare il tutto. Per qualsiasi domanda potete postare i vostri commenti al termine di ogni articolo. </p>
<p>Ovviamente non è finita qui.<br />
Ancora non ho deciso cosa tratterà la quinta parte, che comunque sarà disponibile il più presto possibile.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2008/11/30/zend-framework-introduzione-al-componente-zend_form/' rel='bookmark' title='Permanent Link: Zend Framework: introduzione al componente Zend_Form'>Zend Framework: introduzione al componente Zend_Form</a> <small>Creare form web con Zend Form Con Zend Framework possiamo...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/08/08/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Costruire un’applicazione reale con Zend Framework ( parte 3 )</title>
		<link>http://razorblade.netsons.org/2008/08/06/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-3/</link>
		<comments>http://razorblade.netsons.org/2008/08/06/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-3/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 14:24:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[two step view]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=26</guid>
		<description><![CDATA[<h2>Layout</h2>
Utilizzando le conoscenze acquisite, implementeremo ora un layout leggermente più complesso in modo da prendere realmente domestichezza con la <b>Two Step View</b> per poter quindi passare al vero passo successivo, ovvero la realizzazione del primo modello.<a href="http://razorblade.netsons.org/2008/08/06/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-3/">[...] Continua</a>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Layout</h2>
<p>Utilizzando le conoscenze acquisite, implementeremo ora un layout leggermente più complesso in modo da prendere realmente domestichezza con la <strong>Two Step View</strong> per poter quindi passare al vero passo successivo, ovvero la realizzazione del primo modello.</p>
<p>Aprimo il nostro IndexController, modificando il contenuto esistente con questo nuovo contenuto:</p>
<pre name="code" class="php">  class IndexController extends Zend_Controller_Action {
    public function init(){
      $response = $this-&gt;getResponse();
      $response-&gt;insert('header', $this-&gt;view-&gt;render('header.phtml'));
      $response-&gt;insert('menu', $this-&gt;view-&gt;render('menu.phtml'));
      $response-&gt;insert('columnLeft', $this-&gt;view-&gt;render('columnLeft.phtml'));
      $response-&gt;insert('columnRight', $this-&gt;view-&gt;render('columnRight.phtml'));
      $response-&gt;insert('footer', $this-&gt;view-&gt;render('footer.phtml'));
    }

    public function indexAction(){
      $this-&gt;view-&gt;pageTitle = 'Paesidelmondo Application Example';
      $this-&gt;view-&gt;bodyTitle = 'Paesidelmondo';
      $this-&gt;view-&gt;bodyContent = '

One morning, when Gregor Samsa woke [...]

';
    }
  }
</pre>
<p>Per evitare spreco di spazio ho omesso il contenuto di $this-&gt;view-&gt;bodyContent, che potete sostituire con ciò che vi pare. Abbiamo modificato il metodo init() inserendo all&#8217;interno del $response il contenuto dei file header.phtml, menu.phtml, columnLeft.phtml, columnRight.phtml e footer.phtml, file che creeremo all&#8217;interno di views\scripts e che conterranno:</p>
<h3>header.phtml</h3>
<pre name="code" class="php">
<h1>Paesidelmondo Header</h1>
</pre>
<h3>menu.phtml</h3>
<pre name="code" class="php">
<ul>
<li>Pagina 17</li>
<li>Pagina 18</li>
<li>Pagina 19</li>
<li>Pagina 20</li>
</ul>
</pre>
<h3>columnLeft.phtml</h3>
<pre name="code" class="php">
<h2>Menù Sx</h2>
<ul>
<li>Pagina 1</li>
<li>Pagina 2</li>
<li>Pagina 3</li>
<li>Pagina 4</li>
<li>Pagina 5</li>
<li>Pagina 6</li>
<li>Pagina 7</li>
<li>Pagina 8</li>
</ul>
</pre>
<h3>columnRight.phtml</h3>
<pre name="code" class="php">
<h2>Menù Dx</h2>
<ul>
<li>Pagina 9</li>
<li>Pagina 10</li>
<li>Pagina 11</li>
<li>Pagina 12</li>
<li>Pagina 13</li>
<li>Pagina 14</li>
<li>Pagina 15</li>
<li>Pagina 16</li>
</ul>
</pre>
<h3>footer.phtml</h3>
<pre name="code" class="php">
Powered By Razorblade</pre>
<h3>layout.phtml</h3>
<pre name="code" class="php">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html;charset=utf-8" /&gt;
    &lt;title&gt;&lt;?php echo $this-&gt;escape($this-&gt;pageTitle); ?&gt;&lt;/title&gt;
    &lt;link rel="stylesheet" href="&lt;?php echo $this-&gt;baseUrl(); ?&gt;/css/main.css" type="text/css"&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;!-- start container --&gt;
    &lt;div id="container"&gt;

      &lt;!-- start subContainer --&gt;
      &lt;div id="subContainer"&gt;

        &lt;!-- start header --&gt;
        &lt;div id="header"&gt;&lt;?php echo $this-&gt;layout()-&gt;header;?&gt;&lt;/div&gt;
        &lt;!-- end header --&gt;

        &lt;!-- start menu --&gt;
        &lt;div id="menu"&gt;&lt;?php echo $this-&gt;layout()-&gt;menu;?&gt;&lt;/div&gt;
        &lt;!-- end menu --&gt;

        &lt;!-- start columnLeft --&gt;
        &lt;div id="columnLeft"&gt;&lt;?php echo $this-&gt;layout()-&gt;columnLeft;?&gt;&lt;/div&gt;
        &lt;!-- end columnLeft --&gt;

        &lt;!-- start content --&gt;
        &lt;div id="content"&gt;&lt;?php echo $this-&gt;layout()-&gt;content ?&gt;&lt;/div&gt;
        &lt;!-- end content --&gt;

        &lt;!-- start columnRight --&gt;
        &lt;div id="columnRight"&gt;&lt;?php echo $this-&gt;layout()-&gt;columnRight;?&gt;&lt;/div&gt;
        &lt;!-- end columnRight --&gt;

        &lt;!-- start footer --&gt;
        &lt;div id="footer"&gt;&lt;?php echo $this-&gt;layout()-&gt;footer;?&gt;&lt;/div&gt;
        &lt;!-- end footer --&gt;

      &lt;/div&gt;
      &lt;!-- end subContainer --&gt;

    &lt;/div&gt;
    &lt;!-- end container --&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>L&#8217;index.phtml può restare invariato, per completezza comunque questo è il codice che lo compone:</p>
<h3>index.phtml</h3>
<pre name="code" class="php">
<h2>&lt; ?php echo $this-&gt;bodyTitle ;?&gt;</h2>

&lt; ?php echo $this-&gt;bodyContent ;?&gt;</pre>
<p>Per finire posto il codice css:</p>
<h3>main.css</h3>
<pre name="code" class="php">
	/**************************************************************************
	* Layout CSS
	* Scritto da Sergio Rinaudo
	* Validato W3C
	**/

	/**************************************************************************
	* Stili Generici
	**/

	* {
		margin:0;
		padding:0;
		border:0;
		border-style:solid;
	}  

	body {
		height: 100%;
		color: #85859c;
		font-family: tahoma, arial, sans-serif;
		font-size: 10px;
		text-align: center;
	}  

	h1 {
		margin:0px;
		padding:0px;
	}

	h2{
		margin:0px;
		padding:0px;
	}

	h3 {
		margin:0px;
		padding:0px;
	}

	h4 {
		margin:0px;
		padding:0px;
	}

	h5 {
		margin:0px;
		padding:0px;
	}

	h6 {
		padding:0px;
		margin:0px;
	}

	ul {
		list-style-type:none;
		margin:0px;
		padding:0px;
	}

	li {
		margin:0px;
		padding:0px;
		list-style-type:none;
	}

	div {
		margin:0px;
		padding:0px;
	}

	p {
		margin:0px;
		padding:0px;
	}

	a {
		text-decoration:none;
		color:#0e7bb7;
	}

	a:hover {
		margin:0px ;
		padding:0px;
		color:#5488cc;
		text-decoration:none;
	}

	a:visited {
		margin:0px ;
		padding:0px;
		color:#5488cc;
		text-decoration:none;
	}

	br {
		margin:0px;
		padding:0px;
	}

	img {
		margin:0px;
		padding:0px;
	}

	b {
		margin:0px;
		padding:0px;
	}

	i {
		margin:0px;
		padding:0px;
	}

	u {
		margin:0px;
		padding:0px;
	}

	table {
		margin:0px;
		padding:0px;
	}

	tr {
		margin:0px;
		padding:0px;
	}

	td {
		margin:0px;
		padding:0px;
	}

	form {
		margin:0px;
		padding:0px;
	}

	input {
		margin:0px;
		padding:0px;
	}

	fieldset {
		margin:0px;
		padding:0px;
	}

	legend {
		margin:0px;
		padding:0px;
	}

	label {
		margin:0px;
		padding:0px;
	}

	textarea {
		margin:0px;
		padding:0px;
	}

	span {
		display: none;
	}

	/**************************************************************************
	* Stili Sito
	**/

	#container {
		margin: 0px auto;
		width: 100%;
		border-color: #9e9ec3;
		border-width: 0px 0px 0px;
		border-style: solid;
	}

	#subContainer {
		margin: 0px auto;
		width: 100%;
		border: 0px solid #9e9ec3;
	}

	#container #subContainer #header {
		height: 80px;
		overflow: hidden;
		width: 100%;
		border: 0px solid #000000;
	}

	#container #subContainer #menu {
		margin-bottom: 1px;
		width: 100%;
		height: 21px;
		border-top: 1px solid #9e9ec3;
		border-bottom: 1px solid #9e9ec3;

	}

	#container #subContainer #menu ul {
		list-style-type: none;
		float: left;
		width: auto;
		border: 0px solid #000000;
		overflow: hidden;
		width: 100%;
	}

	#container #subContainer #menu li {
		width: 25%;
		height: 19px;
		float: left;
		overflow: hidden;
		text-align: center;
		font-size: 11px;
		font-weight: bold;
		padding-top: 3px;
	}

	#container #subContainer #menu li a {
		padding-top: 3px;
		width: 129px;
		height: 19px;
	}

	#container #subContainer #columnLeft {
		float:left;
		width: 20%;
		margin: 0px;
		border: 0px solid #48c000;
		text-align: center;
	}

	#container #subContainer #columnLeft ul {
		font-weight:bold;
		width: 100%;
		border-right: 1px solid #9e9ec3;
	}

	#container #subContainer #columnLeft ul li {
		padding: 2px 0px 2px 0px;
		width: 100%;
		border-bottom: 1px solid #9e9ec3;
		margin: 0px auto;
	}

	#container #subContainer #columnLeft ul li a {
		width: 100%;
		padding: 2px;
		color: #9e9ec3;
	}

	#container #subContainer #content {
		width: 60%;
		height: auto;
		margin: 0px;
		border: 0px solid #ff0000;
		float:left;
		text-align:center;
	}

	#container #subContainer #content p {
		padding: 10px ;
	}

	#container #subContainer #columnRight {
		float: right;
		width: 20%;
		margin: 0px;
		border: 0px solid black;
	}

	#container #subContainer #columnRight ul {
		font-weight:bold;
		width: 100%;
		border-left: 1px solid #9e9ec3;
	}

	#container #subContainer #columnRight ul li {
		padding: 2px 0px 2px 0px;
		width: 100%;
		border-bottom: 1px solid #9e9ec3;
		margin: 0px auto;
	}

	#container #subContainer #columnRight ul li a {
		width: 100%;
		padding: 2px;
		color: #9e9ec3;
	}

	#container #subContainer #footer {
		border: 0px solid black;
		clear: both;
		width: 100%;
		height: 90px;
	}

	#container #subContainer #footer p {
		width: 100%;
		border: 0px solid black;
		padding: 2px;
	}
</pre>
<p>Un&#8217;ultima nota prima di chiudere: non possiamo utilizzare $this-&gt;nomeVariabile all&#8217;interno dei file inclusi in init.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/08/06/costruire-un%e2%80%99applicazione-reale-con-zend-framework-parte-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Costruire un&#8217;applicazione reale con Zend Framework ( parte 2 )</title>
		<link>http://razorblade.netsons.org/2008/08/06/costruire-unapplicazione-reale-con-zend-framework-parte-2/</link>
		<comments>http://razorblade.netsons.org/2008/08/06/costruire-unapplicazione-reale-con-zend-framework-parte-2/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 12:07:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[two step view]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=25</guid>
		<description><![CDATA[<h2>Two Step View</h2>
In un gran numero di siti accade che alcune parti del layout cambino poco o non cambino proprio al cambiare della pagina. Per ogni azione richiesta si avrà il relativo controller che avrà la relativa vista che sarà un file .phtml. Per mantenere <a href="http://razorblade.netsons.org/2008/08/06/costruire-unapplicazione-reale-con-zend-framework-parte-2/">[...] Continua</a>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Two Step View</h2>
<p>In un gran numero di siti accade che alcune parti del layout cambino poco o non cambino proprio al cambiare della pagina. Per ogni azione richiesta si avrà il relativo controller che avrà la relativa vista che sarà un file .phtml. Per mantenere il sito uniforme, una possibile soluzione sarebbe di includere all&#8217;interno di ogni file .phtml un codice del genere:</p>
<pre class="php" name="code">&lt; ?php echo $this-&gt;render('header.phtml'); ?&gt;
&lt; ?php echo $this-&gt;title; ?&gt;
&lt; ?php echo $this-&gt;content; ?&gt;
&lt; ?php echo $this-&gt;render('footer.phtml'); ?&gt;
</pre>
<p>Siccome la <b>ridondanza</b> del codice è una cosa che ai programmatori non dovrebbe piacere per vari motivi, giunge in nostro aiuto la <b>Two Step View.<br />
La </b><b>Two Step View</b> consiste nel separare le parti comuni del nostro layout con la parte che effettivamente sarà aggiornata al cambiare della pagina.<br />
Apriamo quindi il file IndexController.php e modifichiamo il suo contenuto con il seguente:</p>
<pre class='php' name='code'>
  class IndexController extends Zend_Controller_Action {
    public function init(){
      $response = $this->getResponse();
      $response->insert('sidebar', $this->view->render('sidebar.phtml'));
    }

    public function indexAction(){
      $this->view->pageTitle = 'Paesidelmondo Application Example';
      $this->view->bodyTitle = '
<h1>Paesidelmondo</h1>

';
      $this->view->bodyContent = '

One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible
      vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches
      into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared
      with the size of the rest of him, waved about helplessly as he looked. "What\'s happened to me? " he thought. It wasn\'t a dream.

 His room, a proper human room although a little too small, lay peacefully between its four familiar walls. A collection of textile samples
      lay spread out on the table - Samsa was a travelling salesman - and above it there hung a picture that he had recently cut out of an illustrated
      magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff
      that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather.

 Drops of rain could be heard hitting the pane, which made him feel quite sad. "How about if I sleep a little bit longer and forget all
      this nonsense", he thought, but that was something he was unable to do because he was used to sleeping on his right, and in his present state
      couldn\'t get into that position. However hard he threw himself onto his right, he always rolled back to where he was. He must have tried it
      a hundred times, shut his eyes so that he wouldn\'t have to look at the floundering legs, and only stopped when he began to feel a mild, dull
      pain there that he had never felt before. "Oh, God", he thought, "what a strenuous career it is that I\'ve chosen! Travelling day in and day
      out. Doing business like this takes much more effort than doing your own business at home, and on top of that there\'s the curse of travelling,
      worries about making train connections, bad and irregular food, contact with different people all the time so that you can never get to know
      anyone or become friendly with them. It can all go to Hell! " He felt a slight itch 

';
    }
  }
</pre>
<p>Apriamo o creiamo in caso ancora non l&#8217;avessimo fatto il file sidebar.phtml all&#8217;interno di views/scripts.<br />
Per questo esempio, creeremo un file molto molto semplice:</p>
<pre name='code' class='php'>
<h2>Menù</h2>
<ul>
<li>Pagina 1</li>
<li>Pagina 2</li>
<li>Pagina 3</li>
<li>Pagina 4</li>
<li>Pagina 5</li>
<li>Pagina 6</li>
<li>Pagina 7</li>
<li>Pagina 8</li>
</ul>
</pre>
<p>Il file index.phtml su views\scripts sarà composto da 2 linee di codice:</p>
<pre name='code' class='php'>
< ?php echo $this->bodyTitle ;?>
< ?php echo $this->bodyContent ;?>
</pre>
<p>Ed infine il file layout.phtml salvato all&#8217;interno di views\layouts :</p>
<pre name='code' class='php'>
&lt; !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html;charset=utf-8" /&gt;
    &lt;title&gt;&lt; ?php echo $this-&gt;escape($this-&gt;pageTitle); ?&gt;&lt;/title&gt;
    &lt;link rel="stylesheet" href="&lt;?php echo $this-&gt;baseUrl(); ?&gt;/css/main.css" type="text/css"&gt;
  &lt;/link&gt;&lt;/head&gt;
  &lt;body&gt;
    &lt;!-- start sidebar --&gt;
    &lt;div id="sidebar"&gt;&lt; ?php echo $this-&gt;layout()-&gt;sidebar; ?&gt;&lt;/div&gt;
    &lt;!-- end sidebar --&gt;

    &lt;!-- start content --&gt;
    &lt;div id="content"&gt;&lt; ?php echo $this-&gt;layout()-&gt;content ?&gt;&lt;/div&gt;
    &lt;!-- end content --&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Che cosa è successo? Come potete notare nel file IndexController.php, abbiamo aggiunto il metodo init,  che intercetta l&#8217;oggetto $response e gli inietta sidebar.phtml al cui contenuto potremo accedere tramite la chiamata $this->layout()->sidebar; all&#8217;interno del file layout.phtml.<br />
Abbiamo quindi risolto il problema della ridondanza del codice in maniera elegante.</p>
<p>Nel nostro layout abbiamo inoltre utilizzato un view helper, baseUrl, utile per caricare il css.<br />
Il seguente è il codice del baseUrl view helper, da inserire nella directory degli helper, che di default su zend framewor si trova in application\views\helpers</p>
<h3>BaseUrl.php</h3>
<pre name="code" class="php">
< ?php

  class Zend_View_Helper_BaseUrl
  {
    function baseUrl(){
      $fc = Zend_Controller_Front::getInstance();
      $request = $fc->getRequest();
      return $request->getBaseUrl();
    }
  }
</pre>
<p>Infine, per concludere con questa seconda parte, l&#8217;ultima modifica da implementare risiede nel file index.php, ovvero il nostro file di bootstrap. Sostituite questo codice:</p>
<pre name="code" class="php">
  // Blocco 4
  $frontController->dispatch();
</pre>
<p>con questo codice:</p>
<pre name="code" class="php">
 // Blocco 4
 try {
   $frontController->dispatch();
  } catch(Exception $e) {
      echo nl2br($e->__toString());
  }
</pre>
<p>Questa modifica è autoesplicativa, non fa altro che inserire il metodo dispatch() all&#8217;interno di un costrutto try/catch in modo da catturare un errore nell&#8217;eventualità che si presenti.</p>
<p>&nbsp;</p>
<h1>Links</h1>
<p><a href="http://akrabat.com/2007/12/11/simple-zend_layout-example/" target="_blank" title="akrabat.com">akrabat.com</a></p>
<p><a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Layout" target="_blank" title="framework.zend.com">framework.zend.com</a></p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/08/06/costruire-unapplicazione-reale-con-zend-framework-parte-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Costruire un&#8217;applicazione reale con Zend Framework ( parte 1 )</title>
		<link>http://razorblade.netsons.org/2008/07/24/costruire-unapplicazione-reale-con-zend-framework-parte-1/</link>
		<comments>http://razorblade.netsons.org/2008/07/24/costruire-unapplicazione-reale-con-zend-framework-parte-1/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 09:13:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[applicazioni con zend framework]]></category>
		<category><![CDATA[registry pattern]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[Zend_registry]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=24</guid>
		<description><![CDATA[In questo articolo realizzeremo una vera applicaziione utilizzando <strong>zend framework</strong>. Il punto di partenza sarà la nostra applicazione <strong>Hello world</strong> discussa in <a href="http://razorblade.netsons.org/2008/07/09/introduzione-a-zend-framework/">questo articolo</a>.

Iniziamo con il modificare e aggiungere alcune directory all'albero della nostra applicazione. <a href="http://razorblade.netsons.org/2008/07/24/costruire-unapplicazione-reale-con-zend-framework-parte-1/">[...] Continua</a>


Related posts:<ol><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li></ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>In questo articolo realizzeremo una vera applicaziione utilizzando <strong>zend framework</strong>. Il punto di partenza sarà la nostra applicazione <strong>Hello world</strong> discussa in <a href="http://razorblade.netsons.org/2008/07/09/introduzione-a-zend-framework/">questo articolo</a>.</p>
<p>Iniziamo con il modificare e aggiungere alcune directory all&#8217;albero della nostra applicazione. Per questo progetto avremo bisogno di rinominare la directory  &#8216;zend&#8217; in &#8216;paesidelmondo&#8217;, nome che daremo al nostro vero progetto. Aggiungiamo quindi &#8216;db&#8217; all&#8217;interno di questa directory. Quindi aggiungeremo le directories &#8216;css&#8217;, &#8216;img&#8217; e &#8216;js&#8217; all&#8217;interno della root. La seguente è la rappresentazione grafica dell&#8217;albero dell&#8217;applicazione:</p>
<ul class="applicationThree">
<li>paesidelmondo
<ul>
<li>application
<ul>
<li>controllers</li>
<li>models</li>
<li>views
<ul>
<li>scripts
<ul>
<li>index</li>
<li>error</li>
</ul>
</li>
<li>layouts</li>
<li>filters</li>
<li>helpers</li>
</ul>
</li>
</ul>
</li>
<li>db</li>
<li>library
<ul>
<li>Zend</li>
</ul>
</li>
<li>tests
<ul>
<li>controllers</li>
<li>models</li>
</ul>
</li>
</ul>
</li>
<li>web_root (www)
<ul>
<li>css</li>
<li>img</li>
<li>js</li>
</ul>
</li>
</ul>
<h2>Caricamento automatico delle classi</h2>
<p>Il file di bootstrap della nostra applicazione <strong>Hello World</strong> è un buon inizio.<br />
Tuttavia dobbiamo procedere ad effettuare diverse modifiche, tra le quali il caricamento automatico delle classi.</p>
<pre class="php" name="code">require_once(’Zend/Loader.php’);
Zend_Loader::loadClass(’Zend_Debug’);
Zend_Loader::loadClass(’Zend_Controller_Front’);</pre>
<p>Come potete notare da questa porzione di codice, quello che abbiamo definito &#8216;blocco 2&#8242;, il caricamento delle classi avviene tramite una chiamata statica, Zend_Loader::loadClass(). In una vera applicazione esiste la necessità di dover caricare un<br />
gran numero di classi. Per questo progetto useremo la funzionalità del metodo magico <strong>__autoload()</strong> di Php 5. Questo metodo usa in modo automatico la funzionalità <strong>spl_autoload_register()</strong> della<br />
<strong>Standard PHP Library</strong> (<strong>SPL</strong>).<br />
Questa funzionalità, usando <strong>Zend Framework</strong>, la si può utilizzare effettuando la seguente chiamata:</p>
<pre class="php" name="code">Zend_Loader::registerAutoload()</pre>
<p>In questo modo, ogni qual volta dovremo utilizzare una cerca classe, il file che la definisce sarà caricato in automatico.</p>
<h2>Configurazione</h2>
<p>La configurazione della nostra applicazione è gestita dalla classe Zend_Config e può essere nei formati  XML, Arrays o un file di configurazione INI. In questo articolo utilizzeremo quest&#8217;ultimo metodo.<br />
Creiamo quindi il file di configurazione, config.ini ed inseriamolo all&#8217;interno della directory &#8216;zend&#8217;. Il seguente è un esempio di cosa potrebbe contenere il file di configurazione:</p>
<pre class="php" name="code">[db]
adapter = PDO_MYSQL
database.host = localhost
database.username = mio_utente
database.password = mia_password
database.name = mio_db</pre>
<p>Questi dati sono accessibili tramite una interfaccia Object Oriented, utilizzando la classe Zend_Config_Ini</p>
<pre class="php" name="code">$config = new Zend_Config_Ini(ZEND_ROOT.'config.ini', 'db');
$adapter = $config-&gt;adapter;
$databaseHost = $config-&gt;database-&gt;host;</pre>
<p>Da notare che il &#8216;.&#8217; funge come separatore gerarchico, difatti &#8216;host&#8217; di database.host è figlio di &#8216;database&#8217;. Un altro tipo di operatore può essere utilizzato all&#8217;interno del file di configurazione, i due punti &#8216;:&#8217; ,<br />
come separatore di sezione in modo tale da poter definire un set di configurazioni standard e quindi poterle modificare in base a quale sezione è la sezione di provenienza.</p>
<pre class="php" name="code">[generale]
db.adapter = PDO_MYSQL
db.config.host = localhost
db.config.username = mio_utente
db.config.password = mia_password
db.config.dbname = mio_db

[produzione : generale]
db.config.host = produzione_db.miosito.it

[sviluppo : generale]
db.config.host = sviluppo_db.miosito.it</pre>
<p>Potremo quindi caricare queste configurazioni in diversi modi, per il sistema in produzione:</p>
<pre class="php" name="code">$config = new Zend_Config_Ini(ZEND_ROOT.'config.ini', 'produzione');</pre>
<p>E per il sistema in sviluppo</p>
<pre class="php" name="code">$config = new Zend_Config_Ini(ZEND_ROOT.'config.ini', 'sviluppo');</pre>
<p>In pratica, <strong>Zend Framework</strong> carica tutte le impostazioni di default ( quelle da cui sia produzione che sviluppo derivano ), quindi applica le modifiche in base al tipo di configurazione richiesta.</p>
<p>Ed ecco infine quello che sarà il nostro file di configurazione per questo articolo:</p>
<pre class="php" name="code">[generale]
db.adapter = PDO_MYSQL
db.config.host = localhost
db.config.username = root
db.config.password =
db.config.dbname = xyz

[produzione : generale]

[sviluppo : generale]

[prova : generale]
db.config.dbname = zend</pre>
<h2>Il Registro</h2>
<p>Per applicazioni di grandi dimensioni è sconsigliato usare variabili globali in quanto potrebbero sorgere problemi di sovrascrittura della variabile ( <a href="http://www.google.it/search?hl=it&amp;client=firefox-a&amp;rls=org.mozilla%3Ait%3Aofficial&amp;hs=3SS&amp;q=coupling+of+global+variables&amp;btnG=Cerca&amp;meta=" target="blank">coupling of global variables</a> ). Per ovviare a questo problema Zend Framework offre la classe Zend_Registry. Zend_Registry implementa il Registry design pattern è quindi un ottima soluzione per salvare oggetti che serviranno in diversi punti della nostra applicazione.<br />
Principalmente, gli oggetti che andremo a salvare all&#8217;interno di Zend_Registry saranno $config e $db.<br />
Per salvare un oggetto useremo il metodo Zend_Registry::set(), che salverà l&#8217;oggetto passato ad argomento in un array associativo interno, una chiave per identificare l&#8217;oggetto dovrà quindi essere fornita. Per recuperare un oggetto salvato useremo il metodo Zend_Registry::get(). Inoltre è diponibile la funzionalità Zend_Registry::isRegistered() per verificare che l&#8217;oggetto esista all&#8217;interno del registro.</p>
<h2>Inizializzazione del Database</h2>
<p>Per inizializzare il database dovremo creare un oggetto di tipo Zend_Db_Adapter, che ci verrà restituito da una chiamata al metodo factory della classe Zend_Db. In questo caso, l&#8217;oggetto che ci verrà restituito sarà di tipo Zend_Db_Adapter_Pdo_Mysql. Per far ciò passeremo il nome dell&#8217;adapter e un array di configurazioni come argomenti.<br />
Registriamo quindi l&#8217;oggetto nel registro:</p>
<pre class="php" name="code">// set up database
$db = Zend_Db::factory($config-&gt;db-&gt;adapter, $config-&gt;db-&gt;config-&gt;toArray());
Zend_Db_Table::setDefaultAdapter($db);
Zend_Registry::set('db', $db);</pre>
<h2>Bootstrap Aggiornato</h2>
<p>Il nostro file di bootstrap, index.php, risulterà così strutturato</p>
<pre class="php" name="code">  // Blocco 1
  error_reporting(E_ALL|E_STRICT);
  ini_set('display_errors', true);
  date_default_timezone_set('Europe/Rome');
  $rootDir = dirname(dirname(__FILE__));
  define( 'CONTAINER', 'paesidelmondo/' );
  define( 'ZEND_ROOT', $rootDir.'/'.CONTAINER );
  set_include_path(ZEND_ROOT.'library'.PATH_SEPARATOR.get_include_path());

  // Blocco 2
  require_once('Zend/Loader.php');
  Zend_Loader::registerAutoload();

  // Blocco 3
  $frontController = Zend_Controller_Front::getInstance();
  $frontController-&gt;throwExceptions(true);
  $frontController-&gt;setControllerDirectory(ZEND_ROOT.'application\controllers');

  // Blocco 3b
  $config = new Zend_Config_Ini(ZEND_ROOT.'config.ini', 'prova');  

  // Blocco 3c
  $db = Zend_Db::factory($config-&gt;db-&gt;adapter, $config-&gt;db-&gt;config-&gt;toArray());
  Zend_Db_Table::setDefaultAdapter($db);
  Zend_Registry::set('db', $db);

  // Blocco 4
  $frontController-&gt;dispatch();</pre>
<p>Con questo si conclude la prima parte sul come costruire un&#8217;applicazione reale con Zend Framework. Nella seconda parte dell&#8217;articolo parleremo della <strong>Two Step View</strong> e della sua implementazione all&#8217;interno di Zend Framework.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>Related posts:<ol><li><a href='http://razorblade.netsons.org/2008/12/05/zend-framework-zend_form-con-recaptcha/' rel='bookmark' title='Permanent Link: Zend Framework: Zend_Form con ReCaptcha'>Zend Framework: Zend_Form con ReCaptcha</a> <small>Utilizzare il webservice ReCaptcha per validare i form ReCaptcha è...</small></li><li><a href='http://razorblade.netsons.org/2009/02/02/zend-framework-gestione-dei-moduli-ed-esempio-modulo-di-amministrazione/' rel='bookmark' title='Permanent Link: Zend Framework: gestione dei moduli ed esempio modulo di amministrazione'>Zend Framework: gestione dei moduli ed esempio modulo di amministrazione</a> <small>Come usare Zend_Layout per la gestione dei moduli In quest'articolo...</small></li><li><a href='http://razorblade.netsons.org/2009/08/28/neobazaar-annunci-gratuiti-esempio-di-una-applicazione-sviluppata-con-zend-framework/' rel='bookmark' title='Permanent Link: Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework'>Neobazaar annunci gratuiti: esempio di una applicazione sviluppata con Zend Framework</a> <small>Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend...</small></li></ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/07/24/costruire-unapplicazione-reale-con-zend-framework-parte-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
