Qui di seguito un modo elegante per impostare un filtro sulla rinomina dei files uploadati usando My_Form_Element_File.
Di solito la rinomina del file o dei files uploadati avviene successivamente alla verifica form valido con isValid() ( nel controller o con override del metodo ),
grazie al Zend_Filter_Callback sarà possibile effettuare la procedura di rinomina files specificandola all’istanza dell’elemento, come un qualsiasi altro filtro.

More »

In questo articolo vedremo come creare un form utilizzando Zend_Form, decorators e display group, senza quindi realizzare una view script separata. Si dà per assunto le conoscenze quantomeno base di Zend Framework, Zend Form, Form Elements, Form Validators e Form Filters.

More »

A few days ago I had the need to convert a long form created using the Zend Framework’s Zend_Form component, from a single page form to multi page form.

As you know, Zend Framework, does not include a standard solution for managing multi-page form, so after looking all over the internet, I found several solutions, all very interesting, but none of these allowed me to fully utilize the work already done.

More »

La profilazione delle queries è una procedura che serve per analizzare le prestazioni delle operazioni nel database, per conoscere quante queries effettua una pagina del nostro progetto e quali di queste eventualmente richiedano un’ottimizzazione o un salvataggio del risultato restituito in cache.

Zend Framework offre uno strumento molto interessante per la visualizzazione di questi dati, Zend_Db_Profiler_Firebug, classe che permette la profilazione
delle queries all’interno dell’estensione Firebug per Firefox.

More »

Il ContextSwitch action helper ci permette di scegliere il formato in cui visualizzare i dati della view, oltre al classico html, anche altri formati come per esempio xml o json, nonchè alcuni formati personalizzati che possiamo definire. Questo è decisamente utile per le richieste XmlHttpRequests o la creazione di Web Services.

Utilizzo

Per utilizzare ContextSwitch dovremo definire nel nostro Controller i contesti, ovvero creare un array associativo che relaziona una action ad uno o più formati, quindi inizializzare l’helper nel metodo init()

  class MyController extends Zend_Controller_Action
  {
      public $contexts = array(
          'listato'     => array('xml'),
          'commenti' => array('xml', 'json')
      );
          
      public function init()
      {
          $this->_helper->contextSwitch()->initContext();
      }
          
      public function listatoAction()
      {
          // codice
      }
          
      public function commentiAction()
      {
          // codice
      }
  }

Per ogni nuovo formato associato ad una action avremo la necessità di creare una view script, con estensione {nome-formato}.phtml, nel caso dell’esempio di sopra, listato.xml.phtml e commenti.xml.phtml.
Queste view script definiranno al loro interno il tipo di xml da restituire, prendendo i dati passati dal controller.

Per quanto riguarda il formato json, questo di default non ha la necessità che sia creato un nuovo file della vista ( as esempio commenti.json.phtml ), in quanto sarà Zend Framework ad occuparsi della serializzazione delle variabili della vista.
Questo comportamento può essere modificato settando l’autoserializzazione a false

   $this->_helper->contextSwitch()->setAutoJsonSerialization(false);

Per “switchare” i vari contesti sarà necessario passare la variabile ‘format’ nella richiesta

- {nome-sito}/{nome-controller}/{nome-action}/format/xml
- {nome-sito}/{nome-controller}/{nome-action}/format/json

Oltre che ad indicare la corretta view script da renderizzare, contextSwitch si occupa di

  • Disabilitare il layout, se attivato
  • Settare gli headers appropriati per la risposta
  • Se specificato, richiamare delle funzionalità di callback per il settaggio del contesto e per azioni post-processing

Per esempio, nel caso di richiesta del formato xml il ‘Content-Type’ della risposta sarà settato a ‘text/xml’.

Formati personalizzati ( Custom Context )

ContextSwitch ci offre la possibilità di creare dei formati personalizzati. Per aggiungere un contesto personalizzato ( custom context ) procederemo alla sua aggiunta all’helper

      public function init()
      {
          $this->_helper->contextSwitch()->addContext($context, array $spec)->initContext();
      }

dove $context è il nome che attribuiamo al contesto personalizzato e $spec è un array di opzioni per il nuovo contesto. Queste opzioni sono:

  • suffix: il suffisso del file della vista per il custom context
  • headers: un array di headers dove la chiave è il nome dell’header e il valore è appunto suo valore es array(‘Content-Type’ => ‘text/xml’)
  • callbacks: un array contenente una o più chiavi init o post, che puntano a delle funzionalità PHP usate per l’inizializzazione del contesto o per il suo post-processing.

Oltre che aggiungere il custom context all’helper, per utilizzarlo sarà necessario relazionarlo alle action del controller

      public $contexts = array(
          'listato'     => array('xml'),
          'commenti' => array('xml', 'json',{nome-custom-context})
      );

Se avete dei dubbi sul contextSwitch action helper potete visitare la documentazione ufficiale zend contextSwitch, o in alternativa, lasciare un commento a questo post.

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading ... Loading ...

Di default, Zend Form e relativi validatori restituiscono delle stringhe di testo in lingua inglese in caso i vari campi non siano validati, qui di seguito vedremo in pochi e brevi passaggi come tradurre questi messaggi di errore in maniera praticamente automatizzata utilizzando le traduzioni create dallo stesso team di Zend Framework.

Scaricando il pacchetto full di Zend Framework da qui ( al momento in cui scrivo l’ultima versione disponibile è la 1.10.6 ), oltre che al framework in se possiamo trovare diverse altre directories, una di queste chiamata ‘resources’.
All’interno di resources possiamo trovare la directory ‘languages’ con al suo interno diverse altre directories, ognuna delle quali identifica una lingua.

Procediamo con il copiare l’intera directory ‘languages’ ed incolliamola all’interno del nostro progetto, allo stesso livello delle directories ‘application’ e ‘library’ come consigliato in questa pagina della documentazione ufficiale zend translate using structure.

La struttura della vostra applicazione dovrebbe assomigliare alla seguente:

      /application/
      /languages/it/
      /library/

Inizializzazione

Ora che abbiamo i nostri file al posto giusto dobbiamo procedere a realizzare una nuova funzione _init* all’interno della nostra classe Bootstrap. Quindi apriamola, ed inseriamo il seguente codice

      
      protected function _initLanguage()
      {
          $localeValue = 'it';
         
          $locale = new Zend_Locale($localeValue);
          Zend_Registry::set('Zend_Locale', $locale);   
          $translationPath = dirname( APPLICATION_PATH ) . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . $localeValue;
    
          $translate = new Zend_Translate('array', $translationPath, $localeValue);
         
          Zend_Registry::set('Zend_Translate', $translate);
          Zend_Validate_Abstract::setDefaultTranslator($translate);
          Zend_Form::setDefaultTranslator($translate);
      }

Il nuovo metodo _initLanguage() appena creato istanzia le classi Zend_Locale e Zend_Translate e le inserisce all’interno del registro.
Da notare che il valore di Zend_Locale ( il primo parametro ) è forzato per essere ‘it’.
Per un sistema dove sia previsto lo switch automatico di questo valore in base alla provenienza dell’utente dovrete provvedere alla realizzazione di un plugin, ma questa parte va oltre questo tutorial.

La classe Zend_Translate accetta diversi parametri a costruttore, il primo indica il tipo di adapter da utilizzare. Nel mio caso ho scelto ‘array’, il che indica che le stringhe tradotte saranno salvate in un file contenente un array. Questo approccio è il più semplice da utilizzare a mio avviso, l’unica pecca è che non tutti potrebbero essere capaci di modificare correttamente un array.

L’array dovra essere restituito utilizzando ‘return’ vedi esempio.

Potete trovare il listato degli adapters disponibili visitando la pagina di documentazione ufficiale zend translate adapter.

Le ultime due righe di codice di questo metodo fanno il lavoro di traduzione dei form

          Zend_Validate_Abstract::setDefaultTranslator($translate);
          Zend_Form::setDefaultTranslator($translate);

L’oggetto translate appena creato sarà utilizzato da tutte le istanze di Zend_Form e Zend_Validator per la traduzione dei messaggi di errore.
Provate ad inviare uno qualsiasi dei vostri form o crearne uno ad hoc per test, vedrete tutti i messaggi di errore tradotti in italiano!
Provate quindi a modificare il valore di $localeValue a fr, de o qualsiasi altra lingua inclusa in ‘languages’ :)

Oltre i form

L’oggetto translate appena creato potrà essere utilizzato anche in qualsiasi file di vista della nostra applicazione utilizzando il Translate view helper.
Allo scopo di effettuare una prova, creiamo all’interno della directory ‘it’ ( languages/it/ ) un file chiamato Custom.php ( o qualsiasi nome preferiate ) ed inseriamo al suo interno questo codice

languages/it/Custom.php 

<?php

  return array(
      'test' => utf8_encode('Questa è una stringa di traduzione di prova')
  );

Questo file appena creato sarà automaticamente parsato e le traduzione incluse nell’oggetto translate.
Inseriamo quindi, in un qualsiasi file di view della nostra applicazione, il seguente codice

     $this->translate('test');

Otterremo

     // Questa è una stringa di traduzione di prova 
1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 5.00 out of 5)
Loading ... Loading ...

La normalizzazione della url o canonicalizzazione della url è il processo per il quale differenti URLs sono modificate e standardizzate. L’obiettivo finale è determinare se due o più URLs equivalgono al medesimo documento.

L’inserimento del link canonical nelle intestazioni del documento è importante in quanto aiutiamo i motori di ricerca a capire se lo stesso contenuto è raggiungibile da più URLs ed in caso, comunicare quale fra queste vogliamo sia indicizzato ( in alternativa il motore di ricerca sceglierà per noi ).

Ulteriori informazioni sulla canonicalizzazione delle URLs sono disponibili sulla Guida di Strumenti per i Webmaster di Google e su wikipedia.

Come aggiungere il canonical link in Zend Framework

Per aggiungere il link canonical tra le intestazioni della nostra pagina utilizzeremo l’headLink view helper.

$canonicalUrl = ''; // l'url principale con il quale è possibile raggiungere il documento
$this->headLink(array('rel' => 'canonical','href' => $canonicalUrl),'APPEND');

Il precedente script è da aggiungere in un view script, in caso lo voleste aggiungere in un controller è da utilizzarsi “$this->view->headLink”.
Il risultato che otterremo sarà simile al seguente

<link href="http://la-mia-url-canonical-per-questa-pagina" rel="canonical" />

Nelle ultime release di Firefox, se è presente il link canonical tra le intestazioni del documento vedremo un “C” nella parte destra della barra degli indirizzi,
di colore GRIGIO e disattivo se ci troviamo nella versione del documento raggiunta dall’indirizzo normalizzato, BLU e attivo ( cliccabile ) se ci troviamo nella versione del documento non corrispondente al link specificato come canonical.

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Nasce Neobazaar.com, annunci gratuiti in Italia: interamente sviluppato con Zend Framework

E’ un po’ che non scrivo più su questo mio blog, purtroppo negli ultimi mesi non ho avuto tempo per scrivere nuovi articoli e/o tutorial. Uno dei progetti che più mi ha tenuto impegnato è Neobazaar.com, che allo stato attuale dei lavori si può considerare ad un buon 95% di completamento.

Neobazaar.com è il classico sito di annunci gratuiti, chiunque può inserire un annuncio, e se lo si desidera, ci si iscrive, con la possibilità di poter gestire i propri annunci tramite un pannello di controllo.

L’annuncio rimane online per i 30 giorni successivi alla pubblicazione, dopodichè viene eliminato automaticamente.

In questo articolo voglio descrivervi alcune delle caratteristiche tecniche presenti in questo mio progetto, ed eventualmente rispondere alle vostre domande/consigli/critiche in merito.

SEO: search engine optimization

Sono diversi gli aspetti a cui ho posto attenzione per quanto riguarda l’ottimizzazione per i motori di ricerca, una della quali è la risposta alle richieste da parte del server, ovvero facendo in modo che il tempo di attesa per la restituzione del documento html sia il minore possibile.

A questo scopo sono due i componenti di Zend Framework che si sono resi molto utili: Zend_Search_Lucene e Zend_Cache.

Zend_Search_Lucene, come già descritto in altri articoli in questo blog, è un motore di ricerca su filesystem, che ci permette di liberare dall’onere delle ricerche il nostro database, ma non solo, possiamo recuperare i dati dei nostri documenti direttamente da esso.

Zend_Cache è un altro utilissimo componente di Zend Framework, la sua utilità è di immagazzinare dei dati, presumibilmnete risultato di pesanti query o algoritmi, e riutilizzarli nelle successive richieste per tutto il tempo da noi indicato.

L’utilizzo combinato di questi due componenti nell’applicazione rende la restituzione del codice html estremamente veloce, caratteristica che oltre ad essere potenzialmente utile al fine dell’indicizzazione, è sicuramente gradita agli utenti ( che quindi non chiuderanno la pagina dopo il terzo secondo di vana attesa :) ).

Generazione dinamica dei tag title e description: come saprete, al fine dell’ottimizzazione, bisogna fare in modo di inserire in cima al documento le parole di maggior rilievo, ed ecco l’importanza del tag title. In neobazaar.com il contenuto del tag title è generato dinamicamente, dipendentemente dalla query ricercata, dalla categoria selezionata e dalla location in cui ci si trova. Il suo contenuto è ovviamente coerente al contenuto generale del documento.

Per quanto riguarda il tag description anch’esso è dinamico: sappiamo però che i meta, molto probabilmente, sono ‘ignorati’ dai motori di ricerca al fine del posizionamento nelle serp, ma ‘description’ è comunque utile, in quanto il suo contenuto sarà visualizzato nella serp dei motori di ricerca, ed avrà l’arduo compito di convincere l’utente a cliccare il proprio sito piuttosto che un altro.

Routing: bisogna fare molta attenzione alle url del nostro sito internet, in quanto, pare sia uno degli elementi che i motori di ricerca esaminano al fine dell’indicizzazione e del posizionamento. Queste devono avere principalmente due caratteristiche: devono essere ‘statiche’ e devono contenere le principali keyworks identificative del documento.

In Neobazaar.com ho posto molta attenzione al contenuto delle url: queste infatti sono sempre statiche ( dove per statiche si intendono senza variabili successive al carattere ‘?’ e che magari terminino per ‘.html’ ), sia che si effettui una ricerca, sia che si visiti una categoria o si visiti una pagina di contenuto.

Sulla questione delle ‘location’ bisogna scrivere due righe: infatti Neobazaar.com permette il filtraggio degli annunci al livello nazionale ( di default ), a livello regionale, provinciale e persino comunale ( questa caratteristica è tuttavia attualmente non disponibile ).

Il filtraggio è dato dal routing, la location è data dal nome del sottodominio: questo risultato è stato raggiunto concatenando la route di default di Zend Framework ( una Module Route ) con una Hostname Route

Inoltre il layout è oviamente, completamente tableless…

Conclusioni

E’ ovvio che non ho elencato tutte le caratteristiche di Neobazaar.com. Ho scritto questo post proprio per permettere a chi fosse interessato, di farmi delle domande, ed ovviamente, anche per fare un po’ di sana pubblicità a questo sito in modo da poterlo testare con un minimo di traffico :) .

Quindi, spero di ricevere al più presto una vostra visita nonchè i vostri commenti qui di seguito!

1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 5.00 out of 5)
Loading ... Loading ...

Sono numerose le novità portate dalla nuova versione 1.8.0 di Zend Framework, come per esempio la possibilità di generare un progetto base utilizzando il componente Zend_Tool e lanciare un semplice comando da terminale. Premetto che il tutorial è scritto per gli utenti windows.

Per far ciò abbiamo prima la necessità di apportare alcune modifiche al nostro sistema operativo, niente di complicato, solo aggiungere alcune variabili d’ambiente. Ma andiamo con ordine.

Recatevi a questo indirizzo http://framework.zend.com/download/latest e scaricate la versione di zend framework ‘Zend Framework 1.8.0 Minimal’. Create quindi una directory all’interno di Program Files e chiamatela ZendFrameworkCli, dovreste quindi avere il percorso C:\Program Files\ZendFrameworkCli sul vostro computer.

A questo punto estraete le directories ‘bin’ e ‘library’ dall’archivio scaricato all’interno di C:\Program Files\ZendFrameworkCli. Quindi al suo interno dovreste avere ‘bin’ e ‘library’.

A questo punto recatevi su Pannello di Controllo -> Sistema, label ‘Avanzate’, cliccate sul bottone ‘Variabili d’ambiente’. Cercate quindi la voce ‘Path’ sotto il riquadro ‘Variabili di sistema’ ( quello in basso ). Selezionatelo e cliccate ‘Modifica’. Alla fine della stringa aggiungete ‘;C:\Program Files\ZendFrameworkCli\bin’ , mi raccomando al ; iniziale, è importante in quanto serve a terminare l’ultima path precedentemente inclusa da qualche altra installazione.

Se utilizzate php con wampserver avrete la necessità di aggiungere una variabile di sistema per la locazione dell’eseguibile di php. Usando l’ultima versione di wamp server dovreste aggiungere questa ‘;C:\wamp\bin\php\php5.2.9-2′ ovviamente vi consiglio di controllare se php.exe si trova effettivamente in quella posizione nel vostro computer.

Quindi Riavviate, le nuove modifiche saranno attive.

A questo punto andate su start -> esegui, inserite cmd e date invio: se tutto ha funzionato come si deve, scrivendo ‘zf show version’ vi dovrebbe essere restituito ‘Zend Framework Version: 1.8.0′.

Possiamo quindi creare il nostro progetto, date il comando ‘zf create project zfproject’, dove ‘zfproject’ sarà il nome della directory in cui il vostro progetto sarà creato, potete sostituirlo con quello che volete. Appena il comando avrà terminato di creare il progetto vi comunicherà dove questo è stato salvato, di default all’interno dela vostra cartella documenti.

Per comodità ho preferito spostare la directory creata da Zend_Tool su C:/wamp/ ( o comunque una directory superiore a www ). All’interno della directory contenente il progetto creato abbiamo la cartella ‘public’. Questa sarà da rinominare a vostro piacimento ed inserire nella parte pubblica del vostro webserver.

Se lo ritenete opportuno potete creare un virtual host per la vostra applicazione di prova con zf1.8.0, come spiegato in .

Problemi riscontrati

Ho incontrato qualche problema nel file index.php pubblico creato da zend tool, le costanti generate tramite l’utilizzo della funzione realpath risultavano stranamente vuote, ho apportato quindi alcune modifiche al file, che posto qui di seguito:


  // Define container to application directory
  defined('DS')
      || define('DS',
                (DIRECTORY_SEPARATOR ? DIRECTORY_SEPARATOR
                                           : '/'));   
                                           
  // Define container to application directory
  defined('CONTAINER_DIR')
      || define('CONTAINER_DIR',
                (getenv('CONTAINER_DIR') ? getenv('CONTAINER_DIR')
                                           : 'zend'));  
                                           
  // Define application directory
  defined('APPLICATION_DIR')
      || define('APPLICATION_DIR',
                (getenv('APPLICATION_DIR') ? getenv('APPLICATION_DIR')
                                           : 'application'));
                                           
  // Define library directory
  defined('LIBRARY_DIR')
      || define('LIBRARY_DIR',
                (getenv('LIBRARY_DIR') ? getenv('LIBRARY_DIR')
                                           : 'library'));
                                           
  // Define condiguration directory
  defined('CONFIGS_DIR')
      || define('CONFIGS_DIR',
                (getenv('CONFIGS_DIR') ? getenv('CONFIGS_DIR')
                                           : 'configs'));

  // Define path to application directory
  defined('APPLICATION_PATH')
      || define('APPLICATION_PATH',
                dirname(dirname(dirname(__FILE__))).DS.CONTAINER_DIR.DS.APPLICATION_DIR.DS);

  // Define path to library directory
  defined('LIBRARY_PATH')
      || define('LIBRARY_PATH',
                dirname(APPLICATION_PATH).DS.LIBRARY_DIR.DS);

  // Define path to library directory
  defined('CONFIGS_PATH')
      || define('CONFIGS_PATH',
                APPLICATION_PATH.CONFIGS_DIR.DS);

  // Define application environment
  defined('APPLICATION_ENV')
      || define('APPLICATION_ENV',
                (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
                                           : 'production'));

  // Typically, you will also want to add your library/ directory
  // to the include_path, particularly if it contains your ZF install
  set_include_path(implode(PATH_SEPARATOR, array(
      LIBRARY_PATH,
      get_include_path(),
  )));

  //echo get_include_path();
  //exit;

  /** Zend_Application */
  require_once 'Zend/Application.php';

  // Create application, bootstrap, and run
  $application = new Zend_Application(
      APPLICATION_ENV,
      CONFIGS_PATH.'application.ini'
  );
  
  $application->bootstrap()
              ->run();

Alcune costanti come potete vedere, prendono un valore se lo trovano all’interno dell’htaccess, altrimenti ne utilizzano uno di default. Le uniche due costanti che hanno la necessità di essere specificate sono:

SetEnv APPLICATION_ENV development
SetEnv CONTAINER_DIR zfproject

Le linee di codice qui sopra dovranno essere inserite in cima all’.htaccess.

Richiamando l’indirizzo locale dove avete inserito la parte pubblica ( o richiamando il vhost creato ), otterrete il seguente risultato

Zend Tool Zend Framework 1.8.0

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
Loading ... Loading ...

Verificare il contenuto dell’indice di Lucene

Se avete seguito questo articolo o comunque state lavorando con un’applicazione fatta con Zend Framework che utilizzi il componente Zend_Search_Lucene, potrebbe essere di grande utilità comprendere esattamente cosa include il vostro Search Index.

A questo scopo vi presento un’utilissima applicazione, Luke, un browser per l’indice di Lucene, che potete recuperare da http://www.getopt.org/luke/ o direttamente da qui (NOTA: richiede Java 1.5 o successivo )

luke_lucene_index_browser

Lo screenshot di sopra rappresenta la schermata iniziale, dove vi sarà richiesto di inserire il percorso dove l’indice di Lucene è salvato. Una volta inserito, vi si presenterà la seguente schermata:

luke_lucene_index_browser

Utilizzo

Vi illustrerò brevemente alcuni possibili utilizzi. Cliccando su un termine rappresentante un campo del vostro indice ( la griglia in basso a sinistra ) e cliccando successivamente il tasto ‘Show top terms’, la griglia alla vostra destra visualizzerà esclusivamente il contenuto del campo selezionato per ogni record, vedi screenshot:

luke_lucene_index_browser

Selezionando la tab ‘Documents’ potrete vedere in dettaglio il contenuto dei vostri documenti ed il tipo di indicizzazione usato. Tramite la tab ‘Search’ potrete effettuare le ricerche, che presumibilmente daranno lo stesso risultato della vostra applicazione.

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...