Fork me on GitHub

Benvenuto

Sul Web ci sono molte informazioni datate che portano gli utenti PHP fuori strada, propagando cattive abitudini e codice non sicuro. PHP: La Retta Via è una guida di riferimento veloce e facile da leggere contenente le migliori tecniche di sviluppo PHP, gli standard popolari di scrittura del codice, link a tutorial autorevoli sparsi per il Web e quelle che secondo gli autori sono attualmente le migliori pratiche.

Non c’è un solo modo corretto di usare PHP. Questo sito Web mira a presentare ai nuovi sviluppatori PHP alcuni argomenti che potrebbero non prendere mai in considerazione, se non troppo tardi, e mira a fornire ai professionisti alcune idee fresche riguardo procedure che hanno usato per anni senza mai aggiornarle. Questo sito Web inoltre non ti dirà mai quali strumenti usare, ma invece offrirà suggerimenti per opzioni multiple, spiegando le differenze nell’approccio e nei casi di utilizzo.

Questo è un documento in sviluppo e continuerà a essere aggiornato con nuove informazioni utili ed esempi non appena saranno disponibili.

Traduzioni

PHP: La Retta Via è tradotto in molte lingue diverse:

Come contribuire

Aiuta questo sito Web a diventare la migliore risorsa per i nuovi programmatori PHP! Contribuisci su GitHub

Spargi la voce!

PHP: La Retta Via ha immagini banner che puoi usare sul tuo sito Web. Mostra il tuo supporto e fai sapere ai nuovi sviluppatori PHP dove possono trovare buone informazioni.

Vedi banner

Torna su

Per iniziare

Usa l’ultima versione stabile (7.0)

Se hai appena iniziato con PHP, assicurati di usare l’ultima versione stabile di PHP 7.0. Il team di PHP ha aggiunto nuove potenti funzionalità rispetto alle vecchie versioni del ramo 5.x.

Potresti trovarti a usare ancora, nel prossimo futuro, PHP 5.x, la cui ultima versione è 5.6. Non è una cattiva opzione, ma dovresti provare ad aggiornare presto all’ultima versione stabile, perché PHP 5.6 non riceverà aggiornamenti di sicurezza dopo il 2018. L’aggiornamento è molto facile, non ci sono molte incompatibilità. Se non sei sicuro della versione o delle funzionalità presenti, verifica la documentazione sul sito php.net.

Il Web server integrato

Con PHP 5.4 o successivo, puoi iniziare a studiare PHP senza installare e configurare un web server completo. Per avviare il server, esegui il seguente comando dal terminale nella web root del tuo progetto:

> php -S localhost:8000

Configurazione Mac

OS X viene fornito con una versione pre-pacchettizzata di PHP, ma è normalmente un po’ più vecchia dell’ultima versione stabile. Mountain Lion ha la 5.3.10, Mavericks ha la 5.4.17 e Yosemite ha la 5.5.9, ma con PHP 5.6 già rilasciato di solito non è abbastanza.

Ci sono diversi modi per installare PHP su OS X.

Installare PHP tramite Homebrew

Homebrew è un potente gestore di pacchetti per OS X che può aiutarti a installare facilmente PHP e varie estensioni. Homebrew PHP è un repository che contiene “formule” per Homebrew relative a PHP e ti permetterà di installare PHP.

A questo punto, puoi installare php53, php54, php55 o php56 usando il comando brew install e cambiando la versione attiva modificando la variabile PATH.

Installare PHP tramite Macports

Il progetto MacPorts è un’iniziativa della comunità open source per il design di un sistema di semplice utilizzo per la compilazione, l’installazione e l’aggiornamento di software open source per linea di comando, X11 o Acqua sul sistema operativo OS X.

MacPorts supporta i binari precompilati, quindi non devi ricompilare le dipendenze dai sorgenti ogni volta. È un salvavita se non hai alcun pacchetto installato sul sistema.

In questo momento puoi installare php53, php54, php55 o php56 usando il comando port install. Per esempio:

sudo port install php54
sudo port install php55

E puoi eseguire il comando select per cambiare la versione attiva di PHP:

sudo port select --set php php55

Installare PHP tramite phpbrew

phpbrew è uno strumento per l’installazione e la gestione di versioni multiple di PHP. Può essere molto utile se due applicazioni/progetti differenti richiedono versioni differenti di PHP e non stai usando le macchine virtuali.

Compilare il sorgente

Un’altra opzione che ti fornisce controllo sulla versione di PHP che installi è compilarlo tu stesso. In questo caso assicurati di avere installato Xcode o il sostituto di Apple “Strumenti da riga di comando per XCode”, scaricabile dal Centro Sviluppatori Mac di Apple.

Installatori all-in-one

Le soluzioni elencate sopra gestiscono principalmente solo PHP, e non forniscono cose come Apache, Nginx o un server SQL. Le soluzioni “all-in-one” come MAMP e XAMPP installeranno questi altri software per te e li integreranno l’uno con l’altro, ma la facilità d’installazione compromette la flessibilità.

Configurazione Windows

Puoi installare PHP su Windows in diversi modi. Puoi scaricare i binari e, fino a poco tempo fa, potevi usare un installer ‘.msi’. L’installer non è più disponibile e si ferma a PHP 5.3.0.

Per l’apprendimento e lo sviluppo locale puoi usare il webserver integrato in PHP 5.4 e superiori, in modo da non doverlo configurare. Se preferisci un pacchetto “all-in-one” che include un webserver e MySQL, allora strumenti come Web Platform Installer, [Zend Server CE][zsce], XAMPP e WAMP ti aiuteranno a configurare un ambiente di sviluppo Windows in men che non si dica. Detto questo, questi strumenti saranno diversi dall’ambiente di produzione, quindi fai attenzione alle differenze se stai sviluppando su Windows ma pubblicando su Linux.

Se devi far girare un ambiente di produzione su Windows, allora IIS7 ti fornirà quello più stabile e performante. Puoi usare phpmanager (un plugin GUI per IIS7) per rendere più semplice la configurazione e la gestione di PHP. IIS7 integra già FastCGI, devi solo configurare PHP come handler. Per supporto e ulteriori informazioni, c’è un’area dedicata a PHP su iis.net.

Torna su

Stile di codifica

La comunità PHP è grande e diversificata, fatta di innumerevoli librerie, framework e componenti. È comune per gli sviluppatori PHP scegliere diversi di questi e combinarli in un singolo progetto. È importante che il codice PHP aderisca (il più fedelmente possibile) a uno stile di codifica comune per rendere facile agli sviluppatori mischiare e usare diverse librerie nei loro progetti.

Il Framework Interop Group ha proposto e approvato una serie di raccomandazioni di stile. Non tutte riguardano lo stile del codice, ma quelle che lo riguardano sono note come PSR-0, PSR-1, PSR-2 e PSR-4. Queste raccomandazioni non sono che una lista di regole che alcuni progetti come Drupal, Zend, Symfony, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium etc. stanno iniziando ad adottare. Puoi usarle in uno dei tuoi progetti, o continuare a usare il tuo stile personale.

Idealmente dovresti scrivere codice PHP che aderisce ad uno standard noto. Può essere una qualunque combinazione dei PSR o uno degli standard di codifica di PHP o Zend. Questo significa che altri sviluppatori potranno facilmente leggere e lavorare col tuo codice, e le applicazioni che implementano i componenti potranno essere consistenti anche quando lavorano con molto codice di terze parti.

Puoi usare PHP_CodeSniffer per controllare che il codice rispetti queste raccomandazioni, e plugin per editor di testo come Sublime Text 2 per avere feedback in tempo reale.

Puoi sistemare la disposizione del codice automaticamente usando uno dei due strumenti disponibili. Uno è il PHP Coding Standards Fixer di Fabien Potencier, testato scrupolosamente. È più grande e più lento, ma molto stabile e usato da alcuni grandi progetti come Magento e Symfony. Un’altra opzione è php.tools, reso popolare dal plugin per editor [sublime-phpfmt][sublime-phpmft]. Nonostante sia nuovo, porta molti miglioramenti sotto il punto di vista della performance, quindi l’adattamento in tempo reale nell’editor è più fluido.

La lingua inglese è preferita per tutti i nomi di simboli e infrastrutture del codice. I commenti possono essere scritti in qualunque lingua facilmente comprensibile da tutte le parti presenti e future che dovranno lavorare sul codice.

Torna su

Caratteristiche del linguaggio

Paradigmi di programmazione

PHP è un linguaggio flessibile e dinamico che supporta diverse tecniche di programmazione. Si è evoluto moltissimo negli ultimi anni, in particolare aggiungendo un solido modello a oggetti in PHP 5.0 (2004), le funzioni anonime e i namespace in PHP 5.3 (2009) e i trait in PHP 5.4 (2012).

Programmazione orientata agli oggetti

PHP ha un set molto completo di funzionalità riguardanti la programmazione orientata agli oggetti inclusi il supporto per le classi, le classi astratte, le interfacce, l’ereditarietà, i costruttori, la clonazione, le eccezioni e altro.

Programmazione funzionale

PHP supporta le funzioni di prima classe, il che significa che una funzione può essere assegnata a una variabile. Ci si può riferire tramite variabili sia alle funzioni definite dall’utente che a quelle native, ed entrambe possono essere invocate dinamicamente. Le funzioni possono essere passate ad altre funzioni come argomenti (caratteristica chiamata Funzioni di ordine superiore) e le funzioni possono restituire altre funzioni.

La ricorsione, una caratteristica che permette a una funzione di chiamare se stessa, è supportata dal linguaggio, ma la maggior parte del codice PHP è incentrato sull’iterazione.

Le nuove funzioni anonime (con supporto per le chiusure) esistono da PHP 5.3 (2009).

PHP 5.4 ha aggiunto la possibilità di legare le chiusure allo scope di un oggetto e ha migliorato il supporto per i callback in modo che possano essere usati quasi sempre in modo intercambiabile con le funzioni anonime.

Metaprogrammazione

PHP supporta varie forme di metaprogrammazione tramite meccanismi come la Reflection API e i metodi magici. Ci sono diversi metodi magici disponibili come __get(), __set(), __clone(), __toString(), __invoke() etc. che permettono agli sviluppatori di modificare il funzionamento di una classe. Gli sviluppatori Ruby dicono spesso che a PHP manca il metodo method_missing, ma è disponibile sotto il nome di __call() e __callStatic().

Namespace

Come menzionato sopra, la comunità PHP ha molti sviluppatori che creano molto codice. Questo significa che il codice PHP di una libreria potrebbe usare lo stesso nome di un’altra per una classe. Quando entrambe le librerie vengono usate nello stesso namespace, potrebbero collidere e causare problemi.

I namespace risolvono questo problema. Come descritto nel manuale di PHP, si può pensare ai namespace come directory del sistema operativo che dividono i file; due file con lo stesso nome possono esistere in directory separate. Allo stesso modo, due classi PHP con lo stesso nome possono esistere in namespace PHP separati. È così semplice.

È importante inserire il codice in un namespace in modo che possa essere usato da altri sviluppatori senza paura che esso collida con altre librerie.

Nel dicembre 2013 il PHP-FIG ha creato un nuovo standard per l’autoloading: PSR-4, che un giorno probabilmente rimpiazzerà PSR-0. Attualmente entrambi sono ancora utilizzabili, perché PSR-4 richiede PHP 5.3 e molti progetti che supportano solo PHP 5.2 attualmente implementano PSR-0. Se userai un autoloader standard per una nuova applicazione o pacchetto allora vorrai quasi sicuramente dare un’occhiata a PSR-4.

Un modo raccomandato di usare i namespace è delineato nel [PSR-4], che mira a fornire una convenzione standard per la i nomi di file, classi e namespace, in modo da consentire la scrittura di codice plug-and-play.

Nell’ottobre 2014 il PHP-FIG ha deprecato il precedente standard di autoloading, PSR-0, che è stato sostituito con PSR-4. Attualmente entrambi sono ancora utilizzabili, giacché PSR-4 richiede PHP 5.3 e molti progetti solo per PHP 5.2 implementano attualmente PSR-0. Se hai intenzione di usare uno standard di autoloading per una nuova applicazione o pacchetto, probabilmente PSR-4 è la scelta giusta.

Standard PHP Library

La Standard PHP Library (SPL) è distribuita con PHP e fornisce un insieme di classi e interfacce. È fatta principalmente di strutture di dati di uso comune (pile, code, cumuli etc.) e iteratori che possono navigare attraverso queste strutture o attraverso le tue classi che implementano le interfacce SPL.

Interfaccia da linea di comando

PHP è stato creato per scrivere applicazioni Web, ma è anche utile nella creazione di programmi da linea di comando (CLI). I programmi da linea di comando aiutano ad automatizzare compiti come il testing, la pubblicazione e l’amministrazione dell’applicazione.

I programmi PHP CLI sono potenti perché puoi usare il codice della tua applicazione direttamente, senza dover creare una GUI sicura. Accertati solo di non mettere gli script CLI nella root pubblica!

Prova ad eseguire PHP dalla tua linea di comando:

> php -i

L’opzione -i visualizzerà la tua configurazione PHP proprio come la funzione phpinfo.

L’opzione -a fornisce una shell interattiva, simile all’IRB di Ruby o alla shell interattiva di Python. Ci sono anche altre opzioni utili.

Scriviamo un semplice programma “Hello, $name”. Per provarlo, crea un file chiamato hello.php come nell’esempio.

<?php
if ($argc !== 2) {
    echo "Utilizzo: php hello.php [name].\n";
    exit(1);
}
$name = $argv[1];
echo "Hello, $name\n";

PHP imposta due variabili speciali a seconda degli argomenti con cui viene eseguito il tuo script. $argc è una variabile intera contenente il numero degli argomenti e $argv è un array contenente il valore di ciascun argomento. Il primo argomento è sempre il nome del tuo file PHP, in questo caso hello.php.

L’espressione exit() è usata con un numero diverso da zero per far sapere alla shell che l’esecuzione del comando è fallita. Codici di uscita comunemente usati possono essere trovati qui.

Per eseguire lo script sopra dalla linea di comando:

> php hello.php
Utilizzo: php hello.php [nome]
> php hello.php world
Hello, world

Xdebug

Uno degli strumenti più utili nello sviluppo software è un buon debugger. Ti permette di tracciare l’esecuzione del codice e monitorare i contenuti dello stack. Xdebug, il debugger di PHP, può essere utilizzato da diversi IDE per fornire punti di interruzione e ispezioni dello stack. Può anche permettere a strumenti come PHPUnit e KCacheGrind di eseguire analisi della copertura del codice e di profilatura.

Se ti trovi con le mani legate e utilizzando var_dump/print_r non riesci ancora a trovare la soluzione, forse devi usare il debugger.

L’installazione di XDebug può essere complessa, ma una delle sue funzioni più importanti è il debug da remoto. Se sviluppi codice localmente e lo testi in una macchina virtuale o su un altro server, il debug da remoto è la funzione che dovresti abilitare immediatamente.

Solitamente dovrai modificare il tuo virtual host o file .htaccess con questi valori:

php_value xdebug.remote_host=192.168.?.?
php_value xdebug.remote_port=9000

L’opzione remote_host e remote_port corrispondono al tuo computer locale e alla porta su cui fai ascoltare l’IDE. A questo punto si tratta solo di mettere l’IDE in modalità di ascolto e caricare l’URL:

http://tuo-sito.example.com/index.php?XDEBUG_SESSION_START=1

Il tuo IDE intercetterà lo stato attuale durante l’esecuzione dello script, permettendoti di impostare punti di interruzione e ispezionare i valori in memoria.

I debugger grafici rendono molto semplice navigare nel codice, ispezionare variabili ed eseguire codice nel runtime attivo. Molti IDE hanno il supporto integrato o tramite plugin per il debugging grafico tramite Xdebug. MacGBDp è una GUI per Xdebug gratuita, open-source e stand-alone dedicata al Mac.

Torna su

Gestione delle dipendenze

Ci sono moltissime librerie PHP, framework e componenti tra cui scegliere. Il tuo progetto, probabilmente, ne userà diversi. Queste sono dipendenze del progetto. Fino a poco tempo fa, PHP non aveva un buon modo per gestire le dipendenze del progetto. Anche se le gestivi manualmente, dovevi comunque preoccuparti degli autoloader. Non più.

Attualmente ci sono due grandi sistemi di gestione dei pacchetti per PHP: Composer e PEAR. Composer è il gestore di pacchetti principale per PHP, ma per lungo tempo PEAR ha ricoperto quel ruolo. Sapere cos’è PEAR è una buona idea perché potresti trovare diversi riferimenti a esso, anche se non lo userai mai.

Composer e Packagist

Composer è un ottimo gestore delle dipendenze per PHP. Elenca le dipendenze del tuo progetto in un file composer.json e, con pochi semplici comandi, Composer scaricherà automaticamente le dipendenze e imposterà l’autoloading al posto tuo.

Ci sono già molte librerie PHP che sono compatibili con Composer pronte per essere usate nel tuo progetto. Questi “pacchetti” sono elencati su Packagist, il repository ufficiale per le librerie PHP disponibili tramite Composer.

Come installare Composer

Puoi installare Composer localmente (nella tua directory di lavoro; ma questo non è più consigliato) o globalmente (es. /usr/local/bin). Supponiamo tu lo voglia installare localmente. Dalla directory root del tuo progetto:

curl -s https://getcomposer.org/installer | php

Questo scaricherà composer.phar (un archivio PHP binario). Puoi eseguirlo con php per gestire le dipendenze del tuo progetto. Attenzione: se esegui direttamente del codice proveniente dal Web, controllalo online per assicurarti che sia sicuro.

Installazione su Windows

Per gli utenti Windows il modo più facile di configurare tutto è usare l’installer [ComposerSetup][6], che esegue un’installazione globale e imposta la variabile $PATH in modo che si possa chiamare composer nella linea di comando da qualunque directory.

Come installare Composer (manualmente)

L’installazione manuale di Composer è una tecnica avanzata; tuttavia, ci sono diverse ragioni per cui uno sviluppatore potrebbe preferire questo metodo rispetto alla procedura di installazione interattiva. L’installazione interattiva controlla la tua versione di PHP per assicurarsi che:

Poiché un’installazione manuale non esegue alcuno di questi controlli, dovrai decidere se il lavoro vale la pena. Ecco come installare Composer manualmente:

curl -s https://getcomposer.org/composer.phar -o $HOME/local/bin/composer
chmod +x $HOME/local/bin/composer

La directory $HOME/local/bin (o una directory di tua scelta) dovrebbe essere nella variabile di ambiente $PATH. In questo modo il comando composer sarà disponibile.

Quando incontri documentazione che dice di eseguire Composer con php composer.phar install, puoi sostituirlo con:

composer install

Questa sezione presumerà che tu abbia installato composer globalmente.

Come definire e installare dipendenze

Composer tiene traccia delle dipendenze del tuo progetto in un file chiamato composer.json. Puoi gestirlo manualmente se preferisci, o usare lo stesso Composer. Il comando composer require aggiunge una dipendenza del progetto e, se non hai un file composer.json, lo crea. Ecco un esempio che aggiunge Twig come dipendenza del tuo progetto:

composer require twig/twig:~1.8

In alternativa puoi usare il comando composer init, che ti guiderà nella creazione di un file composer.json per il tuo progetto. In ogni caso, una volta che hai creato il file composer.json, puoi dire a Composer di scaricare e installare le dipendenze nella cartella vendors/. Questo vale anche per i progetti che hai scaricato e che forniscono un file composer.json:

composer install

Adesso, aggiungi questa linea al file principale della tua applicazione PHP; questo dirà a PHP di usare l’autoloader di Composer per le dipendenze del tuo progetto.

<?php
require 'vendor/autoload.php';

Ora puoi usare le dipendenze del tuo progetto, che saranno caricate automaticamente quando richieste.

Aggiornare le dipendenze

Composer crea un file chiamato composer.lock che contiene la versione esatta di ogni pacchetto che ha scaricato durante l’esecuzione di php composer.phar install. Se condividi il tuo progetto con altre persone e il file composer.lock è parte della distribuzione, quando eseguiranno php composer.phar install otterranno le tue stesse versioni. Per aggiornare le dipendenze, esegui php composer.phar update.

Questo è particolarmente utile quando definisci i tuoi requisiti di versione in maniera flessibile. Per esempio, un requisito di ~1.8 significa “qualunque versione dopo la 1.8.0, ma minore di 2.0.x-dev”. Puoi anche usare il carattere jolly * (es. 1.8.*). Ora il comando di Composer php composer.phar update aggiornerà le dipendenze alla versione più recente che soddisfa i requisiti definiti.

Notifiche di aggiornamento

Per ricevere notifiche riguardo release di nuove versioni puoi registrati a VersionEye, un servizio web che può monitorare i tuoi account GitHub e BitBucket alla ricerca di file composer.json e mandare email con le nuove release dei pacchetti.

Controllare la presenza di vulnerabilità nelle tue dipendenze

Il Security Advisories Checker è un web service e uno strumento da linea di comando. Entrambi esamineranno il file composer.lock e ti diranno se devi aggiornare le tue dipendenze.

Gestire le dipendenze globali con Composer

Composer può anche gestire le dipendenze globali e i loro binari. L’uso è semplice, tutto quello che devi fare è aggiungere il prefisso global al comando. Se per esempio volessi installare PHPUnit globalmente, eseguiresti il seguente comando:

composer global require phpunit/phpunit

Questo creerà una cartella ~/.composer contenente le tue dipendenze globali. Per rendere disponibili ovunque i binari dei pacchetti, dovrai solo aggiungere la cartella ~/.composer/vendor/bin alla tua variabile $PATH.

PEAR

Un altro gestore di pacchetti storico che molti sviluppatori PHP amano è PEAR. Si comporta più o meno come Composer, ma presenta alcune differenze che è bene conoscere.

PEAR richiede che ogni pacchetto abbia una struttura specifica, il che significa che l’autore del pacchetto deve prepararlo per l’utilizzo con PEAR. Usare un progetto che non è stato preparato per l’utilizzo con PEAR non è possibile.

PEAR installa i pacchetti globalmente, il che significa che dopo la prima installazione essi diventano disponibili per tutti i progetti su quel server. Questa può essere una buona cosa se molti progetti utilizzano la stessa versione dello stesso pacchetto, ma può portare a problemi se si creano conflitti di versione tra due progetti.

Come installare PEAR

Puoi installare PEAR scaricando l’installer .phar ed eseguendolo. La documentazione di PEAR ha istruzioni d’installazione dettagliate per ogni sistema operativo.

Se stai usando Linux, puoi anche dare un’occhiata al gestore di pacchetti della tua distribuzione. Debian e Ubuntu, per esempio, hanno un pacchetto APT php-pear.

Come installare un pacchetto

Se un pacchetto è elencato nella lista di pacchetti PEAR, puoi installarlo specificando il suo nome ufficiale:

pear install foo

Se il pacchetto è hostato su un altro canale, dovrai prima scoprire il canale e specificarlo durante l’installazione. Vedi la documentazione sull’uso dei canali per più informazioni su questo argomento.

Gestire le dipendenze PEAR con Composer

Se stai già usando Composer e vorresti installare del codice PEAR, puoi usare Composer per gestire le tue dipendenze PEAR. Questo esempio installerà codice da pear2.php.net:

{
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear2.php.net"
        }
    ],
    "require": {
        "pear-pear2/PEAR2_Text_Markdown": "*",
        "pear-pear2/PEAR2_HTTP_Request": "*"
    }
}

La prima sezione "repositories" verrà usata per far sapere a Composer che deve “inizializzare” (o “scoprire” nella terminologia PEAR) il repository PEAR. Poi nella sezione require viene aggiunto un prefisso al nome del pacchetto, così:

> pear-channel/Package

Il prefisso “pear” è fisso per evitare conflitti, poiché un canale PEAR potrebbe essere identico al nome del distributore di altri pacchetti. In questo modo il nome del canale (o l’URL completo) può essere usato per riferirsi al canale in cui si trova il pacchetto.

Il codice installato viene messo nella directory vendors/ ed è automaticamente disponibile tramite l’autoloader di Composer:

vendor/pear-pear2.php.net/PEAR2_HTTP_Request/pear2/HTTP/Request.php

Per usare questo pacchetto PEAR scrivi semplicemente:

<?php
$request = new pear2\HTTP\Request();

Torna su

Pratiche di codifica

Le basi

PHP è un linguaggio vasto che permette a programmatori di ogni livello di produrre codice non solo velocemente, ma efficientemente. Tuttavia, avanzando nell’apprendimento del linguaggio, ci scordiamo spesso le basi che abbiamo imparato (o su cui abbiamo sorvolato) in favore di scorciatoie e/o cattive pratiche. Per aiutare a combattere questo male comune, questa sezione mira a ricordare ai programmatori delle pratiche di codifica di base in PHP.

Data e ora

PHP ha una classe chiamata DateTime che aiuta nella lettura, scrittura, confronto e calcolo di date e ore. Non ci sono molte funzioni relative alle date e all’ora in PHP a parte DateTime, ma essa fornisce una interfaccia orientata agli oggetti ai casi di uso più comuni. Può gestire i fusi orari, ma ciò esula da questa breve introduzione.

Per iniziare a lavorare con DateTime, converti le rappresentazioni grezze di date e ora in un oggetto con il metodo createFromFormat() o esegui new \DateTime per ottenere la data e l’ora attuali. Usa il metodo format() per convertire DateTime in una stringa da visualizzare.

<?php
$raw = '22. 11. 1968';
$start = DateTime::createFromFormat('d. m. Y', $raw);

echo 'Data inizio: ' . $start->format('Y-m-d') . "\n";

Il calcolo con DateTime è possibile grazie alla classe DateInterval. DateTime ha dei metodi come add() e sub() che prendono un DateInterval per argomento. Non scrivere codice che presume ci sia lo stesso numero di secondi in ogni giorno, sia l’ora legale che i cambiamenti nel fuso orario altereranno i risultati. Invece usa gli intervalli di data. Per calcolare la differenza tra date usa il metodo diff(). Restituirà un nuovo DateInterval, che è molto facile da visualizzare.

<?php
// crea una copia di $start e aggiungi un mese e 6 giorni
$end = clone $start;
$end->add(new DateInterval('P1M6D'));

$diff = $end->diff($start);
echo 'Differenza: ' . $diff->format('%m mese, %d giorni (total: %a giorni)') . "\n";
// Differenza: 1 mese, 6 giorni (total: 37 giorni)

Sugli oggetti DateTime è possibile eseguire un confronto standard:

<?php
if ($start < $end) {
    echo "L'inizio è prima della fine!\n";
}

Un ultimo esempio per dimostrare l’utilizzo della classe DatePeriod. Viene usata per iterare su eventi ricorrenti. Può prendere due oggetti DateTime, inizio e fine, e l’intervallo per il quale restituirà tutti gli eventi compresi.

<?php
// mostra tutti i giovedì tra $start e $end
$periodInterval = \DateInterval::createFromDateString('first thursday');
$periodIterator = new \DatePeriod($start, $periodInterval, $end, \DatePeriod::EXCLUDE_START_DATE);

foreach ($periodIterator as $date) {
    // visualizza ogni data nel periodo
    echo $date->format('Y-m-d') . ' ';
}

Design pattern

Quando stai costruendo la tua applicazione è d’aiuto usare dei pattern di progettazione del tuo codice e pattern comuni per la struttura complessiva del tuo progetto. Usare pattern comuni è utile perché rende molto più facile gestire il tuo codice e permette ad altri sviluppatori di capire velocemente come tutti i componenti lavorano tra loro.

Se usi un framework la maggior parte del codice di alto livello e la struttura del tuo progetto saranno basati su quel framework, quindi molte delle decisioni riguardanti i pattern vengono fatte al posto tuo. Ma è comunque una tua scelta quella dei migliori pattern da seguire nel codice che crei appoggiandoti a quel framework. Se, d’altra parte, non stai usando un framework per creare la tua applicazione allora dovrai trovare i pattern che si adattano meglio al tipo e alle dimensioni dell’applicazione che stai costruendo.

Lavorare con UTF-8

Questa sezione è stata originariamente scritta da Alex Cabal su PHP Best Practices ed è stata usata come base per i nostri consigli su UTF-8.

Non c’è una soluzione unica. Sii attento, dettagliato e consistente.

Attualmente PHP non supporta Unicode al basso livello. Ci sono dei modi per assicurarsi che le stringhe UTF-8 vengano processate correttamente, ma non è semplice, ed è necessario scavare in quasi tutti i livelli dell’applicazione web, dall’HTML all’SQL al PHP. Cercheremo di scrivere un sommario breve e pratico.

UTF-8 al livello PHP

Le operazioni di base con le stringhe, come il concatenamento di due stringhe e l’assegnamento di stringhe a variabili, non richiedono nulla di speciale per il supporto UTF-8. Tuttavia la maggior parte delle funzioni per le stringhe, come strpos() e strlen(), richiedono particolare considerazione. Queste funzioni hanno solitamente una controparte mb_*: per esempio, mb_strpos() e mb_strlen(). Queste stringhe mb_* vengono fornite tramite l’Estensione Multibyte String, e sono specificatamente disegnate per operare su stringhe Unicode.

Devi usare le funzioni mb_* ogni qualvolta operi su una stringa Unicode. Per esempio, se usi substr() su una stringa UTF-8, c’è una buona possibilità che il risultato includa dei caratteri incomprensibili. La funzione corretta da usare sarebbe la controparte multibyte, mb_substr().

La parte difficile è ricordarsi di usare le funzioni mb_* ogni volta. Se ti dimentichi anche una sola volta, la tua stringa Unicode rischia di divenire incomprensibile durante le operazioni successive.

Non tutte le funzioni per le stringhe hanno una controparte mb_*. Se non ce n’è una per quello che vuoi fare, allora peggio per te.

Inoltre, dovresti usare la funzione mb_internal_encoding() all’inizio di ogni script PHP che scrivi (o in cima al tuo script incluso globalmente), e la funzione mb_http_output() subito dopo se il tuo script invia dati a un browser. Definire esplicitamente la codifica delle tue stringhe in ogni script ti salverà molti futuri mal di testa.

Infine, molte funzioni PHP che operano sulle stringhe hanno un parametro opzionale che ti permette di specificare la codifica dei caratteri. Dovresti sempre esplicitamente indicare UTF-8 quando ne hai la possibilità. Per esempio, htmlentities() ha un’opzione per la codifica dei caratteri, e dovresti sempre specificare UTF-8 se hai a che fare con certe stringhe. Tieni a mente che, a partire da PHP 5.4.0, UTF-8 è la codifica predefinita per htmlentities() e htmlspecialchars().

Infine, se stai costruendo un’applicazione distribuita e non sei certo che l’estensione mbstring sarà disponibile, considera l’idea di usare il pacchetto Composer patchwork/utf8. Questo userà mbstring se è disponibile, e le funzioni non UTF-8 se non lo è.

UTF-8 al livello database

Se il tuo script PHP accede a MySQL, è possibile che le tue stringhe vengano salvate nel database come stringhe non UTF-8 anche se segui tutte le precauzioni di cui sopra.

Per assicurarti che le tue stringhe vadano da PHP a MySQL come UTF-8, assicurati che il set e la collation di caratteri del tuo database e delle tue tabelle siano impostati a utf8mb4, e usa il set di caratteri utf8mb4 nella stringa di connessione PDO. Vedi l’esempio di codice sotto. Questo è estremamente importante.

Tieni a mente che devi usare il set di caratteri utf8mb4 per il supporto completo a UTF-8, non il set di caratteri utf8! Vedi Ulteriori letture per scoprire perché.

UTF-8 al livello browser

Usa la funzione mb_http_output() per assicurarti che il tuo script PHP invii stringhe UTF-8 al tuo browser.

Il browser avrà poi bisogno di sapere dalla risposta HTTP che questa pagina dev’essere considerata come UTF-8. L’approccio storico è usare il <meta> tag charset nel tag <head> della tua pagina. Questo approccio è perfettamente valido, ma impostare il charset nell’header Content-Type è in realtà molto più veloce.

<?php
// Comunica a PHP che useremo stringhe UTF-8 fino alla fine dello script
mb_internal_encoding('UTF-8');

// Comunica a PHP che invieremo stringhe UTF-8 al browser
mb_http_output('UTF-8');

// La nostra stringa UTF-8 di test
$string = 'Êl síla erin lû e-govaned vîn.';

// Trasforma la stringa in qualche modo con una funzione multibyte
// Nota come, a scopo dimostrativo, tagliamo la stringa a un carattere non ASCII
$string = mb_substr($string, 0, 15);
<<<<<<< HEAD

// Connettiti al database per salvare la stringa trasformata
// Vedi l'esempio PDO in questo documento per maggiori informazioni
// Nota il comando `set names utf8mb4`!
$link = new \PDO(
    'mysql:host=tuo-hostname;dbname=tuo-db;charset=utf8mb4',
    'tuo-username',
    'tua-password',
    array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_PERSISTENT => false
    )
);

// Salva la stringa trasformata come UTF-8 nel nostro database
// Il tuo DB e le tabelle usano il set e la collation di caratteri utf8mb4, giusto?
$handle = $link->prepare('insert into FrasiElviche (Id, Body) values (?, ?)');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->bindValue(2, $string);
$handle->execute();

// Recupera la stringa che abbiamo appena memorizzato per provare che è stata salvata correttamente
$handle = $link->prepare('select * from FrasiElviche where Id = ?');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->execute();

// Salva il risultato in un oggetto che dopo invieremo nel nostro HTML
$result = $handle->fetchAll(\PDO::FETCH_OBJ);

header('Content-Type: text/html; charset=UTF-8');
?><!doctype html>
<html>
    <head>
      <meta charset="UTF-8">
      <title>Pagina di test UTF-8</title>
    </head>
    <body>
        <?php
        foreach($result as $row){
            print($row->Body);  // Questo dovrebbe inviare correttamente la nostra stringa UTF-8 trasformata al browser
        }
        ?>
    </body>
</html>

Ulteriori letture

Torna su

Iniezione delle dipendenze

Da Wikipedia:

L’iniezione delle dipendenze è un design pattern della programmazione software che permette la rimozione di dipendenze cablate a codice e rende possibile cambiarle, durante l’esecuzione o la compilazione.

Questa citazione fa sembrare il concetto molto più complicato di quanto sia in realtà. L’iniezione delle dipendenze consiste nel fornire a un componente le sue dipendenze tramite l’iniezione nel costruttore, chiamate a metodi, o l’impostazione di proprietà. Tutto qui.

Concetto di base

Possiamo dimostrare il concetto con un esempio semplice ma primitivo.

Abbiamo una classe Database che richiede un adattatore per comunicare col database. Istanziamo un adattatore nel costruttore e creiamo una dipendenza cablata a codice. Questo rende il testing difficoltoso e la classe Database fortemente legata all’adattatore.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct()
    {
        $this->adapter = new MySqlAdapter;
    }
}

class MysqlAdapter {}

Questo codice può essere rifattorizzato in modo che usi l’iniezione delle dipendenze, e dunque renda la dipendenza più elastica.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(MySqlAdapter $adapter)
    {
        $this->adapter = $adapter;
    }
}

class MysqlAdapter {}

Ora forniamo alla classe Database la sua dipendenza invece di crearla noi. Potremmo anche creare un metodo che accetti un argomento della dipendenza e impostarla così, o se la proprietà $adapter fosse public potremmo impostarla direttamente.

Problema complesso

Se hai mai letto qualcosa sull’iniezione delle dipendenze allora hai probabilmente visto i termini “Inversione del controllo” o “Principio di inversione della dipendenza”. Questi sono problemi complessi risolti dall’iniezione delle dipendenze.

Inversione del controllo

L’inversione del controllo consiste, come suggerisce il nome, nell’“invertire il controllo” di un sistema tenendo il controllo organizzativo completamente separato dai nostri oggetti. Con l’iniezione delle dipendenze, questo significa rendere le dipendenze più flessibili controllandole e istanziandole in un altro punto del sistema.

Per anni, i framework PHP hanno usato l’inversione del controllo. Tuttavia, la domanda è diventata: quale parte del controllo stai invertendo, e dove? Per esempio, i framework MVC generalmente fornivano un oggetto padre o un controller di base che gli altri controller dovevano estendere per accedere alle sue dipendenze. Questa è inversione del controllo, ma invece di rendere le dipendenze più flessibili, questo metodo semplicemente le spostava.

L’iniezione delle dipendenze ci permette di risolvere questo problema in maniera più elegante, iniettando solo le dipendenze che ci servono, quando ci servono, senza il bisogno di alcuna dipendenza rigida.

Principio di inversione della dipendenza

Il principio di inversione della dipendenza è la “D” nell’insieme di principi di design orientato agli oggetti S.O.L.I.D., secondo cui si dovrebbe “Dipendere dalle astrazioni. Non dipendere dalle concrezioni.” Detto semplicemente, questo significa che le nostre dipendenze dovrebbero essere interfacce/contratti o classi astratte, non implementazioni concrete. Possiamo facilmente rifattorizzare l’esempio sopra in modo che segua questo principio.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }
}

interface AdapterInterface {}

class MysqlAdapter implements AdapterInterface {}

Ci sono diversi benefici all’approccio seguito, in cui la classe Database dipende ora da un’interfaccia piuttosto che da un’implementazione concreta.

Pensa di lavorare in team, e che un collega stia lavorando all’adattatore. Nel nostro primo esempio, avremmo dovuto aspettare che tale collega finisse l’adattore prima di poterlo imitare appropriatamente per i nostri unit test. Ora che la dipendenza è un’interfaccia/contratto, possiamo felicemente imitare quell’interfaccia sapendo che il nostro collega costruirà l’adattatore basandosi su quel contratto.

Un beneficio ancora più grande è che ora il nostro codice è molto più scalabile. Se tra un anno decidiamo che vogliamo migrare verso un tipo diverso di database, possiamo scrivere un adattatore che implementi l’interfaccia originale e iniettare quello. Non servirebbe alcun’altra rifattorizzazione, perché saremmo sicuri che l’adattore segue il contratto stabilito dall’interfaccia.

Contenitore

La prima cosa che dovresti capire riguardo i contenitori di iniezione delle dipendenze è che non sono uguali all’iniezione delle dipendenze. Un contenitore è un’utilità che ti aiuta a implementare l’iniezione delle dipendenze. Tuttavia, possono essere (e spesso sono) usati male per implementare un anti-pattern, la localizzazione dei servizi. Iniettare nelle tue classi un contenitore DI come un localizzatore di servizi crea una dipendenza dal contenitore ancora più forte di quella che stai sostituendo. Inoltre rende il tuo codice molto meno trasparente e più difficile da testare.

La maggior parte dei framework moderni ha il proprio contenitore di iniezione delle dipendenze che ti permette di unire insieme le dipendenze tramite configurazione. Questo significa che puoi scrivere del codice applicativo pulito e indipendente quanto il framework su cui è basato.

Altre letture

Torna su

Database

Molte volte il tuo codice PHP utilizzerà un database per memorizzare informazioni. Hai diverse opzioni per connetterti e interagire con il tuo database. L’opzione consigliata fino a PHP 5.1.0 era di usare i driver nativi come mysqli, pgsql, mssql etc.

I driver nativi vanno bene se usi un database nella tua applicazione ma se, per esempio, stai usando MySQL e un po’ di MSSQL, o devi connetterti a un database Oracle, allora non potrai usare gli stessi driver. Dovrai imparare una nuova API per ogni database e può diventare faticoso.

Estensione MySQL

L’estensione mysql per PHP non è più attivamente sviluppata ed è ufficialmente deprecata a partire da PHP 5.5.0, il che significa che sarà rimossa nei prossimi rilasci. Se nelle tue applicazioni stai usando delle funzioni che iniziano con mysql_* come mysql_connect() o mysql_query(), sappi che nelle versioni successive semplicemente non saranno più disponibili. Questo significa che sarai obbligato a riscrivere il tuo codice a un certo punto, quindi l’opzione migliore è rimpiazzare mysql con mysqli o PDO secondo la tua tabella di marcia; in questo modo dopo non dovrai farlo in fretta e furia.

Se stai iniziando ora, non usare assolutamente l’estensione mysql: usa l’estensione MySQLi o PDO.

Estensione PDO

PDO è una libreria di astrazione della connessione al database (integrata in PHP a partire dalla versione 5.1.0) che fornisce un’interfaccia comune per la comunicazione con molti database differenti. Per esempio, puoi usare praticamente lo stesso codice per interfacciarti con MySQL o SQLite:

<?php
// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'utente', 'password');
$statement = $pdo->query("SELECT un_campo FROM una_tabella");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['un_campo']);

// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT un_campo FROM una_tabella");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['un_campo']);

PDO non tradurrà le tue query SQL e non emulerà le funzionalità mancanti; viene usato solo per connettersi a diversi tipi di database con la stessa API.

Ancora più importante, PDO ti permette di inserire in maniera sicura dell’input esterno (es. ID) nelle tue query SQL senza preoccuparti di attacchi di tipo SQL injection. È possibile farlo grazie agli statement e ai bound parameters di PDO.

Supponiamo che uno script PHP riceva un ID numerico come parametro della query. Questo ID dovrebbe essere usato per recuperare il record di un utente dal database. Ecco il modo sbagliato di farlo:

<?php
$pdo = new PDO('sqlite:/path/db/utenti.db');
$pdo->query("SELECT nome FROM utenti WHERE id = " . $_GET['id']); // <-- NO!

Questo codice è terribile. Stai inserendo direttamente un parametro della query in una query SQL. Questa vulnerabilità sarà sfruttata in un batter d’occhio, usando una pratica chiamata SQL Injection. Immagina solo cosa accadrebbe se un hacker passasse un parametro id fittizio chiamadno un URL come http://domain.com/?id=1%3BDELETE+FROM+users. In questo modo la variabile $_GET['id'] sarebbe impostata a 1;DELETE FROM users, che cancellerebbe tutti i tuoi utenti! Per evitarlo, dovresti sempre pulire l’input ID usando i bound parameters di PDO.

<?php
$pdo = new PDO('sqlite:/path/db/utenti.db');
$stmt = $pdo->prepare('SELECT nome FROM utenti WHERE id = :id');
$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT); // <-- filtra prima i tuoi dati (vedi [Filtraggio dei dati](#data_filtering)), in particolare per operazioni INSERT, UPDATE etc.
$stmt->bindParam(':id', $id, PDO::PARAM_INT); // <-- Pulito automaticamente da PDO
$stmt->execute();

Questo è codice corretto. Usa un bound parameter in uno statement PDO. In questo modo viene effettuato l’escape dell’input esterno ID prima che questo venga introdotto nel database, evitando potenziali attacchi di tipo SQL injection.

Per le operazioni di scrittura, come INSERT e UPDATE, è particolarmente importante filtrare prima i dati e poi pulirli (rimozione di tag HTML, JavaScript etc.). PDO li pulirà solo rispetto all’SQL, non alla tua applicazione.

Dovresti anche tenere in considerazione che le connessioni al database usano risorse, e non sarebbe strano che tali risorse si esaurissero se le connessioni non vengono chiuse implicitamente (ma è più comune in altri linguaggi). Usando PDO, puoi chiudere implicitamente la connessioni distruggendo l’oggetto, ovvero assicurandoti che tutti i rimanenti riferimenti a esso vengano cancellati (impostati a NULL). Se non lo fai esplicitamente, PHP chiuderà automaticamente la connessione quando il tuo script termina l’esecuzione, a meno che, ovviamente, tu non stia usando delle connessioni persistenti.

Interagire coi database

Quando gli sviluppatori iniziano a studiare PHP, spesso finiscono per mescolare l’interazione col database con la logica di presentazione, usando codice come questo:

<ul>
<?php
foreach ($db->query('SELECT * FROM tabella') as $row) {
    echo "<li>".$row['campo1']." - ".$row['campo2']."</li>";
}
?>
</ul>

Questo è una pessima pratica per diverse ragioni: principalmente è difficile da debuggare, difficile da testare, difficile da leggere e stamperà molti campi se non imposti un limite.

Nonostante ci siano molte soluzioni per farlo - a seconda che si preferisca l’OOP o la programmazione funzionale - ci dev’essere un elemento di separazione.

Considera il passo più semplice:

<?php
function getAllFoos($db) {
    return $db->query('SELECT * FROM tabella');
}

foreach (getAllFoos($db) as $row) {
    echo "<li>".$row['campo1']." - ".$row['campo2']."</li>";
}

Questo è un buon inizio. Metti quei due pezzi in due file diversi e hai una separazione pulita.

Crea una classe per metterci quel metodo e hai un “modello”. Crea un semplice file .php per metterci la logica di presentazione e hai una “vista”, che è molto simile all’MVC - un’architettura OOP comune a molti framework.

foo.php

<?php
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'utente', 'password');

// Rendi disponibile il tuo modello
include 'models/FooModel.php';

// Crea un'istanza
$foo = new FooModel($db);

// Effettua la query attraverso un metodo pubblico
$fooList = $foo->getAllFoos();

// Mostra una vista
include 'views/foo-list.php';

models/FooModel.php

<?php
class FooModel()
{
    protected $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function getAllFoos() {
        return $this->db->query('SELECT * FROM tabella');
    }
}

views/foo-list.php

<?php foreach ($fooList as $row): ?>
    <?= $row['campo1'] ?> - <?= $row['campo2'] ?>
<?php endforeach ?>

Questa è essenzialmente la stessa cosa che fanno molti framework moderni, anche se un po’ più manuale. Potresti non averne sempre bisogno, ma mischiare insieme troppa logica di presentazione e interazione col database può essere un problema serio se vorrai mai fare lo unit testing della tua applicazione.

PHPBridge ha un’ottima risorsa chiamata Creating a Data Class che copre un argomento simile, ed è perfetta per sviluppatori che stanno prendendo famigliarità solo ora col concetto di interazione coi database.

Livelli di astrazione

Molti framework forniscono il proprio livello di astrazione, che a volte è basato su PDO. Spesso questi emulano in un sistema di database funzionalità presenti solo in un altro, fornendoti dei metodi PHP per costruire le tue query; in questo modo forniscono un’astrazione reale del database invece della semplice astrazione della connessione fornita da PDO. Ovviamente, questo complica leggermente le cose, ma se stai costruendo un’applicazione portatile che deve funzionare con MySQL, PostgreSQL e SQLite, allora un po’ di complicazione può essere introdotta per avere del codice pulito.

Alcuni livelli di astrazione sono stati costruiti usando gli standard di namespace PSR-0 o PSR-4, in modo che possano essere installati in qualunque applicazione:

Torna su

Templating

I template sono un modo comodo per separare la logica dei controller e quella di dominio dalla logica di presentazione. Tipicamente i template contengono il codice HTML della tua applicazione, ma possono essere usati anche per altri formati, come l’XML. I template vengono spesso chiamati anche “viste”, che costituiscono parte del secondo componente del pattern di architettura del software model–view–controller (MVC).

Benefici

Il beneficio principale derivante dall’uso dei template è la separazione che creano tra la logica di presentazione e il resto della tua applicazione. I template hanno la sola responsabilità di visualizzare contenuto formattato. Non sono responsabili per il recupero o la persistenza dei dati o altri compiti più complessi. Questo porta alla scrittura di codice più pulito e più facile da leggere, particolarmente utile in un team dove gli sviluppatori lavorano sul codice server-side (controller e modelli) e i designer lavorano sul client-side (markup).

I template, inoltre, migliorano l’organizzazione del codice di presentazione. I template sono generalmente posti in una cartella “views”, ciascuno definito in un singolo file. Questo approccio incoraggia il riutilizzo del codice: grandi blocchi di codice vengono spezzati in pezzi più piccoli e riutilizzabili, spesso chiamati template o viste parziali (“partials”). Per esempio, l’header e il footer del tuo sito possono essere definiti ciascuno in un template e venire poi inclusi prima e dopo ciascun template di pagina.

Infine, a seconda della libreria che usi, i template possono offrire maggiore sicurezza eseguendo l’escape automatico del contenuto generato dall’utente. Alcune librerie offrono anche una funzionalità di sand-boxing: in questo caso i designer dei template hanno accesso solo a variabili e funzioni autorizzate.

Template PHP semplici

I template scritti in PHP sono semplicemente dei template che usano codice PHP nativo. Sono una scelta naturale dato che PHP stesso è un linguaggio per i template. Questo significa semplicemente che puoi includere codice PHP in altro codice, come l’HTML. Si tratta di un beneficio per gli sviluppatori PHP perché non c’è nessuna nuova sintassi da imparare, conoscono le funzioni disponibili, e i loro editor PHP hanno già l’evidenziazione della sintassi e l’autocompletamento integrati. Inoltre, i template PHP sono generalmente molto veloci perché non richiedono compilazione.

Ogni framework PHP moderno utilizza qualche tipo di sistema di template, la maggior parte dei quali usano PHP di default. Al di là dei framework, librerie come Plates o Aura.View semplificano il lavoro con i template PHP offrendo funzionalità di templating moderne come l’ereditarietà, i layout e le estensioni.

Esempio semplice di template PHP

Usando la libreria Plates.

<?php // user_profile.php ?>

<?php $this->insert('header', ['title' => 'Profilo utente']) ?>

<h1>Profilo utente</h1>
<p>Ciao, <?=$this->escape($name)?></p>

<?php $this->insert('footer') ?>

Esempio di template PHP con ereditarietà

Usando la libreria Plates.

<?php // template.php ?>

<html>
<head>
    <title><?=$title?></title>
</head>
<body>

<main>
    <?=$this->section('content')?>
</main>

</body>
</html>
<?php // user_profile.php ?>

<?php $this->layout('template', ['title' => 'Profilo utente']) ?>

<h1>Profilo utente</h1>
<p>Ciao, <?=$this->escape($name)?></p>

Template compilati

Nonostante PHP si sia evoluto fino a diventare un linguaggio maturo e orientato agli oggetti, non è migliorato molto come linguaggio di templating. I template compilati, come Twig o Smarty*, sopperiscono a questa mancanza offrendo una nuova sintassi che è stato studiata appositamente per il templating. Dall’escaping automatico all’ereditarietà, passando per le strutture di controllo semplificate, i template compilati sono disegnati per essere più semplici da scrivere, più puliti da leggere e più sicuri da usare. I template compilati possono anche essere condivisi tra diversi linguaggi, e Mustache ne è un buon esempio. Poiché questi template devono essere compilati c’è un leggero impatto sulla performance, ma è minimo quando si usa un sistema di caching appropriato.

*Nonostante Smarty offra l’escaping automatico, questa funzionalità NON è abilitata di default.

Esempio semplice di template compilato

Usando la libreria Twig.

{% include 'header.html' with {'title': 'Profilo utente'} %}

<h1>Profilo utente</h1>
<p>Ciao, {{ name }}</p>

{% include 'footer.html' %}

Esempio di template compilato che usa l’ereditarietà

Usando la libreria Twig.

// template.html

<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>

<main>
    {% block content %}{% endblock %}
</main>

</body>
</html>
// user_profile.html

{% extends "template.html" %}

{% block title %}Profilo utente{% endblock %}
{% block content %}
    <h1>Profilo utente</h1>
    <p>Ciao, {{ name }}</p>
{% endblock %}

Ulteriori letture

Articoli e tutorial

Librerie

Torna su

Errori ed Eccezioni

Errori

In molti linguaggi di programmazione, ogni volta che qualcosa va storto viene lanciata un’eccezione. Questo è certamente un modo possibile di fare le cose, ma PHP è un linguaggio con poche eccezioni. Nonostante supporti le eccezioni e sempre più del codice nativo stia usando a usarle quando si lavora con gli oggetti, la maggior parte di PHP cercherà di continuare a processare indipendentemente da quello che accade, a meno che non avvenga un errore fatale.

Per esempio:

$ php -a
php > echo $foo;
Notice: Undefined variable: foo in php shell code on line 1

Questo è solo un errore notice, e PHP continuerà felicemente. Questo può confondere chi viene da linguaggi con molte eccezioni, perché riferirsi a una variabile mancante in Python, per esempio, lancia un’eccezione:

$ python
>>> print foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

L’unica vera differenza è che Python andrà nel panico per ogni piccola cosa, in modo che gli sviluppatori possano essere completamente sicuri che qualunque potenziale problema o caso limite sia coperto, mentre PHP continuerà a processare a meno che non avvenga qualcosa di estremo; a questo punto lancerà un errore e lo riporterà.

Gravità degli errori

PHP ha diversi livelli di gravità degli errori. I tre tipi più comuni di messaggi sono gli errori, i notice e i warning. Questi hanno diversi livelli di gravità: E_ERROR, E_NOTICE e E_WARNING. Gli errori sono errori fatali che avvengono durante l’esecuzione; sono solitamente causati da problemi nel tuo codice e devono essere sistemati perché impediranno l’esecuzione di PHP. I notice sono messaggi di avviso causati da codice che potrebbe o meno causare problemi durante l’esecuzione dello script; l’esecuzione non viene fermata. I warning sono errori non fatali: l’esecuzione dello script non viene fermata.

Un altro tipo di messaggio di errore riportato durante la compilazione sono i messaggi E_STRICT. Questi messaggi sono usati per suggerire cambiamenti al tuo codice per assicurare la migliore interoperabilità e compatibilità con le versioni successive di PHP.

Cambiare il metodo di segnalazione degli errori in PHP

Il segnalazione degli errori può essere cambiato usando le impostazioni di PHP e/o delle chiamate a funzioni PHP. Usando la funzione nativa di PHP error_reporting() puoi impostare il livello degli errori per la durata dell’esecuzione dello script passando una delle costanti di livello errore predefinite. Questo significa che se vuoi vedere solo warning ed errori - ma non notice - allora puoi configurarlo così:

<?php
error_reporting(E_ERROR | E_WARNING);

Puoi anche controllare se gli errori vengono visualizzati a schermo (ottimo per lo sviluppo) o se vengono nascosti e loggati (ottimo per la produzione). Per maggiori informazioni controlla la sezione Segnalazione degli errori.

Soppressione in linea degli errori

Puoi anche dire a PHP di sopprimere errori specifici usando l’operatore di controllo degli errori @. Metti questo operatore all’inizio di un’espressione, e ogni errore che è un risultato diretto dell’espressione viene silenziato:

<?php
echo @$foo['bar'];

Questo mostrerà $foo['bar'] se esiste, ma restituirà semplicemente un valore nullo e non visualizzerà niente se la variabile $foo o l’indice 'bar' non esistono. Senza l’operatore di controllo degli errori, questa espressione potrebbe creare un errore PHP Notice: Undefined variable: foo o PHP Notice: Undefined index: bar.

Questa potrebbe sembrare una buona idea, ma ci sono alcuni lati negativi. PHP gestisce le espressioni che usano un @ in maniera meno performante rispetto a quelle senza @. L’ottimizzazione prematura potrebbe essere la radice di tutti i dibattiti sulla programmazione, ma se la performance è particolarmente importante per la tua applicazione/libreria, è importante capire le conseguenze che l’operatore di controllo degli errori avrà sulla performance.

In secondo luogo, l’operatore di controllo degli errori inghiotte completamente l’errore. L’errore non viene mostrato, e l’errore non viene mandato al log degli errori. Inoltre, i sistemi PHP di produzione non hanno modo di disabilitare l’operatore di controllo degli errori. Nonostante l’errore che vedi potrebbe essere innocuo, un errore differente e meno innocuo verrebbe ugualmente silenziato.

Se c’è un modo di evitare l’operatore di soppressione degli errori, dovresti consdierarlo. Per esempio, il nostro codice sopra potrebbe essere riscritto così:

<?php
echo isset($foo['bar']) ? $foo['bar'] : '';

Un caso in cui la soppressione degli errori potrebbe avere senso è quando fopen() non trova il file da caricare. Potresti controllare l’esistenza del file prima di provare a caricarlo, ma se il file viene cancellato dopo il controllo e prima di fopen() (il che potrebbe sembrare impossibile, ma può accadere) allora fopen() restituirà false e lancerà un errore. Questo è potenzialmente qualcosa che PHP dovrebbe risolvere, ma è un caso in cui la soppressione degli errori potrebbe sembrare l’unica soluzione valida.

Prima abbiamo detto che non c’è modo in un sistema PHP tradizionale di disabilitare l’operatore di controllo degli errori. Tuttavia, Xdebug ha un’impostazione ini xdebug.scream che disabilita l’operatore di controllo degli errori. Puoi impostarlo nel tuo php.ini scrivendo:

xdebug.scream = On

Puoi anche impostare questo valore durante l’esecuzione con la funzione ini_set:

<?php
ini_set('xdebug.scream', '1')

L’estensione PHP “Scream” offre una funzionalità simile a quella di Xdebug, ma l’impostazione ini di Scream si chiama scream.enabled.

Questo è particolarmente utile quando stai debuggando del codice e sospetti che un messaggio di errore informativo venga soppresso. Usa scream con cura, come uno strumento di debugging temporaneo. Ci sono molte librerie PHP che potrebbero non funzionare con l’operatore di controllo degli errori disabilitato.

ErrorException

PHP è perfettamente in grado di essere un linguaggio fortemente orientato alle eccezioni, e richiede solo qualche linea di codice per fare il cambio. Fondamentalmente puoi lanciare i tuoi “errori” come “eccezioni” usando la classe ErrorException, che estende la classe Exception.

Questa è una pratica comune implementata da un grande numero di framework moderni come Symfony e Laravel. Di default Laravel visualizzerà tutti gli errori e le eccezioni usando il pacchetto Whoops! se l’interruttore app.debug è acceso, oppure li nasconderà se l’interruttore è spento.

Lanciando gli errori come eccezioni durante lo sviluppo puoi gestirli meglio del solito, e se vedi un’eccezione durante lo sviluppo puoi racchiuderla in un’istruzione di cattura con codice specifico per gestire la situazione. Ciascuna eccezione che catturi rende istantaneamente la tua applicazione un po’ più robusta.

Maggiori informazioni su questo e su come usare la classe ErrorException per gestire gli errori si possono trovare su classe ErrorException.

Eccezioni

Le eccezioni sono una parte standard della maggior parti dei linguaggi di programmazione famosi, ma sono spesso ignorate dai programmatori PHP. Linguaggi come Ruby fanno un uso massiccio delle eccezioni, quindi ogni volta che qualcosa va storto come una richiesta HTTP che fallisce, o una query al database che non funziona, o anche se un’immagine non può essere trovata, Ruby (o le gem usate) lancerà un’eccezione a schermo in modo che tu sappia subito che c’è un errore.

PHP stesso è piuttosto negligente in questo senso: una chiamata a file_get_contents() su un file inesistente non farà che restituire FALSE e un warning. Molti vecchi framework PHP come CodeIgniter si limiteranno a restituire false, loggare un messaggio nei loro log proprietari e a volte usare un metodo come $this->upload->get_error() per vedere cos’è andato storto. Il problema qui è che devi cercare l’errore e controllare la documentazione per vedere come recuperare l’errore di quella classe, invece di averlo subito ovvio.

Un altro problema è quando le classi lanciano un errore a schermo automaticamente e terminano il processo. Facendo questo, impedisci a un altro sviluppatore di gestire dinamicamente l’errore. Le eccezioni dovrebbero essere lanciate per mettere a conoscenza lo sviluppatore di un errore; starà a loro scegliere come gestirlo. Esempio:

<?php
$email = new Fuel\Email;
$email->subject('Mio oggetto');
$email->body('Come stai?');
$email->to('guy@example.com', 'Un tizio');

try
{
    $email->send();
}
catch(Fuel\Email\ValidationFailedException $e)
{
    // La validazione è fallita
}
catch(Fuel\Email\SendingFailedException $e)
{
    // Il driver non è riuscito a mandare l'email
}
finally
{
    // Eseguito anche se l'eccezione non è stata lanciata, e prima che la normale esecuzione riprenda
}

Eccezioni SPL

La classe generica Exception fornisce molte poche informazioni di debug per lo sviluppatore; tuttavia, per rimediare a questo, è possibile creare una versione specializzata di Exception estendola:

<?php
class ValidationException extends Exception {}

Questo significa che puoi aggiungere più blocchi catch e gestire differenti eccezioni in modo differente. Questo può portare alla creazione di molte eccezioni personalizzate, alcune delle quali avrebbero potuto essere evitate usando le eccezioni SPL fornite dall’estensione SPL.

Se per esempio usi il metodo magico __call() e un metodo non valido è richiesto, invece di lanciare un’eccezione standard, troppo vaga, o creare un’eccezione personalizzata solo per quello, potresti solo eseguire throw new BadFunctionCallException().

Torna su

Sicurezza

Sicurezza nelle applicazioni Web

Ci sono cattive persone pronte e desiderose di manipolare la tua applicazione Web. È importante che prendi le precauzioni necessarie per irrigidire la sicurezza della tua applicazione Web. Fortunatamente, i ragazzi dell’Open Web Application Security Project hanno compilato una lunga lista di vulnerabilità di sicurezza note e metodi per proteggerti contro di esse. Questa guida dev’essere necessariamente letta da qualunque sviluppatore che abbia a cura la sicurezza.

Hashing delle password

Prima o poi chiunque crea un’applicazione PHP che richiede il login degli utenti. Username e password vengono salvati nel database e usati successivamente per autenticare gli utenti al login.

È importante effettuare un hashing appropriato delle password prima di salvarle. L’hashing delle password è una funzione irreversibile che viene eseguita sulle password degli utenti. Essa produce una stringa a lunghezza fissa che non può essere decriptata. Ciò significa che puoi confrontare l’hash con un altro per determinare se provengono tutti dalla stessa stringa d’origine, ma non puoi determinare la stringa di origine. Se l’hashing delle password non viene effettuato e il tuo database è letto da una persona non autorizzata, tutti gli account utente sono compromessi. Alcuni utenti potrebbero (sfortunatamente) usare la stessa password per altri servizi. Dunque, è importante gestire la sicurezza seriamente.

In PHP 5.5 è stata introdotta la funzione password_hash. In questo momento utilizza l’algoritmo BCrypt, che è il più potente attualmente supportato da PHP. Sarà aggiornata in futuro per supportare altri algoritmi. La libreria password_compat è stata creata per fornire compatibilità per PHP >= 5.3.7.

Nell’esempio sotto calcoliamo l’hash di una stringa, quindi confrontiamo l’hash con una nuova stringa. Poiché le nostre stringhe di origine sono differenti (‘secret-password’ e ‘bad-password’) questo login fallirà.

<?php
require 'password.php';

$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);

if (password_verify('bad-password', $passwordHash)) {
    // password corretta
} else {
    // password sbagliata
}

Filtraggio dei dati

Non fidarti mai (mai!) dell’input esterno introdotto nel tuo codice PHP. Sanitizza e valida sempre l’input prima di usarlo nel tuo codice. Le funzioni filter_var e filter_input possono sanitizzare il testo e validare certi formati (es. indirizzi email).

L’input esterno può essere qualunque cosa: dati di form da $_GET e $_POST, alcuni valori nella variabile superglobale $_SERVER, e il corpo della richiesta HTTP recuperato tramite fopen('php://input', 'r'). Ricorda, l’input esterno non è limitato ai form inviati dall’utente. Anche i file caricati e scaricati, i valori di sessione, i dati nei cookie e i dati da servizi Web di terze parti sono input esterno.

Anche se l’input esterno può essere salvato, combinato e letto successivamente, è ancora input esterno. Ogni volta che processi, visualizzi, concateni o includi dati nel tuo codice, chiediti se sono stati filtrati appropriatamente e se ci si può fidare di essi.

I dati possono essere filtrati diversamente a seconda del loro scopo. Per esempio, quando input esterno non filtrato è passato nell’output HTML della pagina, può esguire codice HTML e JavaScript sul tuo sito! Questo è conosciuto come Cross-Site Scripting (XSS) e può essere un attacco molto pericoloso. Un modo per evitare l’XSS è sanitizzare tutti i dati generati dall’utente prima di visualizzarlo nella tua pagina, rimuovendo i tag HTML con la funzione strip_tags o eseguendo l’escape di caratteri dal significato speciale nelle loro rispettive entità HTML con le funzioni htmlentities o htmlspecialchars.

Un altro esempio è il passaggio di opzioni alla linea di comando. Questo può essere molto pericoloso (ed è solitamente una cattiva idea), ma puoi usare la funzione nativa escapeshellarg per sanitizzare gli argomenti del comando eseguito.

Un ultimo esempio è l’accettazione di input esterno per determinare un file da caricare dal filesystem. Questa vulnerabilità può essere sfruttata cambiando il nome di file in un path di file. Devi rimuovere “/”, “../”, i byte nulli o altri caratteri dal path in modo che non possa caricare file nascosti, non pubblici o con informazioni sensibili.

Sanitizzazione

La sanitizzazione rimuove (o fa l’escape) i caratteri non permessi o pericolosi dall’input esterno.

Per esempio, dovresti sanitizzare l’input esterno prima di includerlo in codice HTML o inserirlo in una query SQL grezza. Quando usi i parametri di PDO, esso sanitizzerà l’input per te.

A volte è richiesto di consnetire alcuni tag HTML sicuri nell’input quando viene incluso nella pagina HTML. Questo è molto difficile da fare e molti lo evitano usando una formattazione più ristretta come Markdown o BBCode, tuttavia esistono alcune librerie come HTML Purifier per svolgere questo compito.

Vedi i filtri di sanitizzazione

Validazione

La validazione serve per assicurarsi che l’input esterno contenga ciò che ti aspetti. Per esempio, potresti voler validare un indirizzo email, un numero di telefono o un’età quando processi una richiesta di registrazione.

Vedi i filtri di validazione

File di configurazione

Nella creazione di file di configurazione per la tua applicazione, le migliori pratiche raccomandano l’utilizzo di uno dei seguenti metodi:

Register globals

NOTA: A partire da PHP 5.4.0 l’opzione register_globals è stata rimossa e non può più essere usata. Questo è incluso solo come avvertimento per chiunque stia aggiornando una vecchia applicazione.

Quando abilitata, l’opzione register_globals farà sì che molti tipi di variabili (incluse quelle da $_POST, $_GET e $_REQUEST) siano disponibili nello scope globale dell’applicazione. Questo può facilmente portare a problemi di sicurezza, perché la tua applicazione non può stabilire con certezza da dove arrivano i dati.

Per esempio: $_GET['foo'] sarebbe disponibile tramite $foo, che può sovrascrivere le variabili non dichiarate. Se stai usando PHP < 5.4.0, assicurati che register_globals sia off.

Segnalazione degli errori

Il logging degli errori può essere utile per trovare i punti problematici della tua applicazione, ma può anche esporre informazioni riguardo la sua struttura al mondo esterno. Per proteggere efficacemente la tua applicazione da problemi che potrebbero essere causati dalla visualizzazioni di questi messaggi, devi configurare il tuo server diversamente negli ambienti di sviluppo e produzione.

Sviluppo

Per mostrare ogni possibile errore durate lo sviluppo, configura le seguenti opzioni nel tuo php.ini:

display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On

Il valore -1 visualizzerà ogni possibile errore, anche quando nuovi livelli verranno aggiunti in versioni future di PHP. Anche la costante E_ALL si comporta in questo modo a partire da PHP 5.4. - php.net

Il livello di errore E_STRICT è stato introdotto nella versione 5.3.0 e non è parte di E_ALL, tuttavia lo è diventato nella 5.4.0. Questo significa che se vuoi segnalare ogni possibile errore nella 5.3 devi usare -1 o E_ALL | E_STRICT.

Segnalare ogni possibile errore nelle diverse versioni di PHP

Produzione

Per nascondere gli errori in produzione configura così il tuo php.ini:

display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On

Con queste impostazioni in produzione, gli errori saranno comunque loggati nei log del web server, ma non saranno visualizzati all’utente. Per maggiori informazioni su queste impostazioni, vedi il manuale di PHP:

Torna su

Testing

Scrivere test automatizzati per il tuo codice PHP è considerata una buona pratica e può portare a un’applicazione ben costruita. I test automatizzati sono un ottimo strumento per assicurarsi che la tua applicazione non si rompa quando cambi qualcosa o aggiungi una nuova funzionalità e non dovrebbero essere ignorati.

Ci sono diversi tipi di strumenti (o framework) per il testing in PHP, ciascuno con un approccio differente; tutti quanti cercano di evitare la necessità di testare manualmente e di assemblare grandi team per il Controllo Qualità solo per assicurarsi che i recenti cambiamenti non rompano funzionalità esistenti.

Test Driven Development

Da Wikipedia:

Il Test Driven Development, in sigla TDD (in italiano: Sviluppo guidato dalle verifiche) è un processo di sviluppo del software in cui lo sviluppo vero e proprio è preceduto (e guidato, driven) dalla stesura di test automatici. Il processo si articola sulla ripetizione di brevi cicli di sviluppo e collaudo (noti come “cicli TDD”, TDD cycles) suddivisi in tre fasi successive, sintetizzate dal motto “Red-Green-Refactor”.

Ci sono molti modi diversi di testare la tua applicazione.

Unit testing

Lo unit testing è un approccio di programmazione usato per assicurarsi che funzioni, classi e metodi funzionino come ci si aspetta durante l’intero ciclo di sviluppo. Controllando i valori di input e output delle funzioni e dei metodi, puoi accertarti che la logica interna funzioni correttamente. Usando l’iniezione delle dipendenze e creando classi mock e stub puoi verificare che le dipendenze vengano usate correttamente per una copertura dei test ancora migliore.

Quando crei una classe o funzione dovresti creare uno unit test per ogni comportamento che deve assumere. Come minimo dovresti assicurarti che generi un errore se le invii argomenti non validi e che funzioni se le invii argomenti validi. Questo aiuterà ad assicurarsi che, quando cambi qualcosa in questa classe o funzione successivamente nel ciclo di sviluppo, la vecchia caratteristica continuerà a funzionare come previsto. L’unica alternativa a questo sarebbe var_dump() in un file test.php, il che non è un modo corretto per creare un’applicazione, sia piccola che grande.

L’altro utilizzo per gli unit test è nel contributo a progetti open source. Se riesci a scrivere un test che mostra una caratteristica non funzionante, lo sistemi e mostri che ora il test passa, le patch saranno accettate molto più facilmente. Se hai intenzione di lanciare un progetto che accetta contributi esterni, questo dovrebbe essere un requisito.

PHPUnit è lo standard de-facto per la scrittura di unit test per applicazioni PHP, ma ci sono diverse alternative:

Integration testing

Da Wikipedia:

L’integration testing (a volte chiamato Integration and Testing, abbreviato “I&T”) è la fase del testing software in cui i moduli individuali vengono combinati e testati come un insieme. Si piazza dopo lo unit testing e prima del validation testing. L’integration testing prende come input moduli su cui è già stato effettuato unit testing, li raggruppa in aggregati più grandi, applica i test definiti nel piano di integration testing a questi aggregati e invia come output il sistema integrato, pronto per l’esecuzione del system testing.

Molti degli strumenti per lo unit testing possono essere usati anche per l’integration testing, giacché molti dei principi di base sono gli stessi.

Functional testing

A volte conosciuto anche come acceptance testing, il functional testing consiste nell’utilizzo di strumenti per la creazione di test automatizzati che usino realmente la tua applicazione invece di limitarsi a verificare che unità individuali di codice si comportino correttamente e riescano a parlare l’una con l’altra. Questi strumenti funzionano generalmente utilizzando dati reali e simulati utenti dell’applicazione esistenti.

Strumenti per il functional testing

Behavior Driven Development

Ci sono due differenti tipi di Behavior-Driven Development (BDD): SpecBDD e StoryBDD. Lo SpecBDD si concentra sul comportamento tecnico del codice, mentre lo StoryBDD si concentra sulle interazioni. PHP ha dei framework per entrambi i tipi di BDD.

Con lo StoryBDD, scrivi delle storie leggibili da esseri umani che descrivono il comportamento della tua applicazione. Queste storia possono poi essere eseguite come veri e propri test per la tua applicazione. Il framework usato nelle applicazioni PHP per lo StoryBDD è Behat, che si ispira al progetto Ruby Cucumber e implementa il DSL Gherkin per la descrizione delle funzionalità.

Con lo SpecBDD, scrivi delle specifiche che descrivono come il tuo codice dovrebbe funzionare. Invece di testare una funzione o un metodo, descrivi come quella funzione o metodo dovrebbero comportarsi. PHP offre il framework PHPSpec per questo scopo. Questo framework si ispira al progetto Ruby RSpec.

Strumenti complementari

Oltre ai framework di testing individuali, ci sono anche altri framework generici e librerie di aiuto utili per ogni approccio.

Torna su

Server e pubblicazione

Le applicazioni PHP possono essere pubblicate ed eseguite sui Web server di produzione in diversi modi.

Platform as a Service (PaaS)

PaaS fornisce il sistema e l’architettura di rete necessari per eseguire applicazioni PHP in Rete. Questo significa che c’è bisogno di poca o nessuna configurazione per lanciare applicazioni e framework PHP.

Recentemente PaaS è diventato un metodo piuttosto usato per la pubblicazione, l’hosting e la scalatura di applicazioni PHP di ogni dimensione. Puoi trovare una lista di provider PHP PaaS “Platform as a Service” nella nostra sezione risorse.

Server virtuali o dedicati

Se hai dimestichezza con l’amministrazione di un sistema o vuoi impararla, i server virtuali o dedicati ti danno totale controllo sull’ambiente di produzione della tua applicazione.

nginx e PHP-FPM

PHP, tramite il FastCGI Process Manager (FPM) integrato, si integra molto bene con nginx, che è un server leggero dalle alte prestazioni. Usa meno memoria di Apache e gestisce meglio le richieste simultanee. Questo è particolarmente importante su server virtuali che non hanno molta memoria.

Apache e PHP

PHP e Apache hanno fatto molta storia insieme. Apache è totalmente configurabile e ha molti moduli che estendono le sue funzionalità. È una scelta comune per i server condivisi e una configurazione facile per i framework PHP e le applicazioni open source come WordPress. Sfortunatamente, Apache usa più risorse di nginx di default e non riesce a gestire così tanti visitatori contemporeanei.

Ci sono molte configurazioni diverse per eseguire Apache con PHP. La più comune e la più semplice da configurare è il prefork MPM con mod_php5. Nonostante questa non sia la più efficiente in termini di consumo di memoria, è la più semplice da configurare e usare. Questa è probabilmente la scelta migliore se non vuoi addentrarti troppo in profondità nell’amministrazione dei server. Nota che per usare mod_php5 DEVI usare il prefork MPM.

In alternativa, se vuoi ottenere migliori performance e stabilità con Apache puoi usare lo stesso sistema FPM di nginx ed eseguire l’[MPM worker] o l’[MPM event] con mod_fastcgi o mod_fcgid. Questa configurazione sarà molto più efficiente nell’utilizzo di memoria e molto più veloce, ma è più complicata da installare.

Server condivisi

PHP deve ringraziare i server condivisi per la sua popolarità. È difficile trovare un host che non abbia PHP installato, ma assicurati che sia l’ultima versione. I server condivisi permettono a te e altri sviluppatori di pubblicare siti sulla stessa machina. Il lato positivo è che si tratta di un sistema economico. Il lato negativo è che non sai mai che tipo di macello i tuoi vicini creeranno; il rallentamento del server o l’apertura di brecce di sicurezza sono pericoli da tenere in considerazione. Se il budget del tuo progetto lo permette, evita i server condivisi.

Costruire e pubblicare la tua applicazione

Se ti trovi a dover modificare lo schema del database o eseguire i test prima dell’aggiornamento dei file manualmente, ripensaci! Con ogni compito manuale in più che devi eseguire per pubblicare una nuova versione della tua applicazione aumentano le possibilità di un errore fatale. Che tu stia gestendo un semplice aggiornamento, un processo di build completo o una strategia di integrazione continua, l’automazione dello sviluppo è tua amica.

Tra i compiti che potresti voler automatizzare ci sono:

Strumenti di automazione dello sviluppo

Questi strumenti possono essere descritti come un insieme di script che gestiscono compiti comuni nella pubblicazione del software. Lo strumento non è parte del tuo software, ma agisce su di esso da ‘fuori’.

Ci sono molti strumenti open source disponibili per aiutarti con l’automazione dello sviluppo, alcuni scritti in PHP, altri no. Questo non dovrebbe impedirti di usarli, se sono più adatti per uno specifico compito. Ecco alcuni esempi.

Phing è il modo più facile per iniziare con la pubblicazione automatica nel mondo di PHP. Con Phing puoi controllare la pacchettizazione, la pubblicazione o il processo di testing tramite un semplice file XML. Phing (che è basato su Apache Ant) fornisce un ricco set di compiti solitamente richiesti per installare o aggiornare un’applicazione Web e può essere esteso con compiti personalizzati, scritti in PHP.

Capistrano è un sistema per programmatori medio-avanzati per eseguire comandi in modo strutturato e ripetibile su una o più macchine remote. È pre- configurato per la pubblicazione di applicazioni Ruby on Rails, ma molti lo usano per pubblicare applicazioni PHP. Il suo corretto utilizzo dipende dalla conoscenza di Ruby e Rake.

Il post PHP Deployment with Capistrano sul blog di Dave Gardner è un buon punto d’inizio per programmatori PHP interessati a Capistrano.

Chef è più di un framework di pubblicazione. È un framework di integrazione di sistema molto potente scritto in Ruby che non solo pubblica la tua applicazione ma può costruire l’intero ambiente server o macchina virtuale.

Deployer è uno strumento di pubblicazione scritto in PHP; è semplice e [funzionale. Esegue i compiti in parallelo, supporta la pubblicazione atomica, [mantiene la consistenza tra i server. Ha ricette per compiti comuni relativi a [Symfony, Laravel, Zend Framework e Yii.

Risorse Chef per sviluppatori PHP

Altre letture:

Integrazione continua

L’integrazione continua è una pratica di sviluppo software in cui i membri di un team integrano il loro lavoro frequentemente. Generalmente ogni persona integra il lavoro almeno giornalmente, portando a più integrazioni giornaliere. Molti team trovano che questo approccio riduca notevolmente i problemi di integrazione e permette a un team di sviluppare software coeso più rapidamente.

– Martin Fowler

Ci sono diversi modi di implementare l’integrazione continua in PHP. Recentemente Travis CI ha fatto un buon lavoro nel rendere l’integrazione continua una realtà anche per piccoli progetti. Travis CI è un sistema hostato di integrazione continua per la community open source. È integrato con GitHub e offre supporto di prima classe per molti linguaggi, incluso PHP.

Altre letture:

Torna su

Virtualizzazione

Eseguire la tua applicazione in un ambiente di produzione diverso da quello di sviluppo può portare alla comparsa di strani errori quando pubblichi la tua applicazione. È anche difficile mantenere i diversi ambienti di sviluppo aggiornati all’ultima versione delle librerie usate quando lavori con un team di sviluppatori.

Se stai sviluppando su Windows e pubblicando su Linux (o qualunque cosa che non sia Windows) o stai sviluppando in un team, dovresti considerare la possibilità di usare una macchina virtuale. Può sembrare complicato, ma oltre agli ambienti di virtualizzazione più conosciuti come VMware e VirtualBox, ci sono strumenti addizionali che potrebbero aiutarti a configurare un ambiente virtuale in pochi semplici passi.

Vagrant

Vagrant ti aiuta a costruire le tue macchine virtuali sfruttando ambienti virtuali noti, e configura questi ambienti basandosi su un singolo file di configurazione. Queste macchine possono essere configurate manualmente, oppure puoi usare un software di “provisioning” come Puppet o Chef per farlo al posto tuo. Eseguire il provisioning della macchina di base è un ottimo modo per assicurarti che più macchine vengano configurate nella stessa maniera e rimuove la necessità di mantenere complicate liste di comandi d’installazione. Puoi anche “distruggere” la macchina e ricrearla senza troppi passi manuali, rendendo così semplice creare un’installazione “fresca”.

Vagrant crea delle cartelle per condividere il codice tra l’host e la tua macchina virtuale, il che significa che puoi creare e modificare file sul tuo host e poi eseguire il codice nella macchina virtuale.

Un po’ di aiuto

Se ti serve un picolo aiuto per iniziare a usare Vagrant ci sono dei servizi che potrebbero essere utili:

Docker

Oltre a usare Vagrant, un altro semplice modo per configurare un ambiente di sviluppo e uno di produzione è Docker. Docker ti aiuta a fornire container Linux per ogni tipo di applicazione. Ci sono molte immagini Docker utili che possono fornirti altri ottimi servizi (es. MySQL, PostgreSQL e molti altri) senza la necessità di installare tali servizi sulla tua macchina locale. Dai un’occhiata al Docker Hub Registry per avere una lista dei contenitori pre-fabbricati disponibili, che potrai poi eseguire ed usare con facilità.

Esempio: Eseguire le tue applicazioni PHP in Docker

Dopo aver installato docker sulla tua macchina, potrai avviare un’istanza di Apache con supporto a PHP in un solo passo. Il comando seguente scaricherà un’installazione di Apache completamente funzionante con l’ultima versione di PHP, e renderà disponibile la directory /path/ai/tuoi/file/php all’indirizzo http://localhost:8080:

docker run -d --name mio-webserver-php -p 8080:80 -v /path/ai/tuoi/file/php:/var/www/html/ php:apache

Dopo aver eseguito docker run il tuo container sarà inizializzato ed eseguito. Se vuoi fermare o avviare nuovamente il tuo container, puoi usare il nome che hai fornito ed eseguire semplicemente docker stop mio-webserver-php e docker start mio-webserver-php senza fornire nuovamente i parametri menzionati sopra.

Altre risorse su Docker

I comandi menzionati sopra mostrano solo un modo veloce per eseguire un web server Apache con supporto a PHP, ma ci sono molte altre cose che puoi fare con Docker. Una delle cose più importanti per gli sviluppatori PHP è collegare il proprio web server con l’istanza di un database, per esempio. La Docker User Guide spiega nel dettaglio come farlo.

Torna su

Caching

PHP è piuttosto veloce già di suo, ma possono sorgere dei problemi quando esegui connessioni remote, carichi file etc. Per fortuna, ci sono diversi strumenti a disposizione per velocizzare certe parti dell’applicazione, o ridurre il numero di volte che questi compiti lenti devono essere eseguiti.

Opcode cache

Quando un nuovo PHP file viene eseguito, è prima compilato in opcode; solo dopo l’opcode viene eseguito. Se un file PHP non viene modificato, l’opcode rimane lo stesso. Questo significa che il processo di compilazione è uno spreco di risorse computazionali.

È qui che le cache dell’opcode entrano in gioco. Evitano compilazioni inutili salvando l’opcode in memoria e riusandolo nelle chiamate successive. Impostare una cache dell’opcode è una questione di minuti, e la tua applicazione sarà molto più veloce. Non c’è alcuna ragione per non usarla.

A partire da PHP 5.5, c’è una cache dell’opcode integrata chiamata OPcache. È anche disponibile per versioni precedenti.

Altre risorse sulle cache dell’opcode:

Caching degli oggetti

Alcune volte può essere utile mettere in cache oggetti singoli nel tuo codice, come, per esempio, dati che sono lenti da ottenere o chiamate al database il cui risultato cambia difficilmente. Puoi usare software di caching degli oggetti per mantenere questi pezzi di dati in memoria per un successivo accesso estremamente veloce. Se salvi questi elementi in un data store dopo averli recuperati, e poi li prendi direttamente dalla cache per le richieste successive, puoi ottenere un notevole miglioramento delle performance e riducendo il carico del tuo database.

Molte soluzioni famose di caching del bytecode ti permettono anche di mettere in cache dati personalizzati, dunque ci sono ancora più ragioni per trarne vantaggio. APCu, XCache e WinCache forniscono tutti API per salvare dati dal tuo codice PHP nella loro memoria cache.

I sistemi di caching degli oggetti più comunemente usati sono APCu e memcached. APCu è una scelta eccellente per il caching degli oggetti. Include una semplice API per aggiungere i tuoi dati alla sua memoria cache ed è molto semplice da configurare e usare. L’unica vera limitazione di APCu è che è legato al Web server su cui è installato. Memcached, invece, è installato come un servizio separato e può essere letto dalla rete, il che significa che puoi memorizzare oggetti in un data store super-veloce in una posizione centrale e molti sistemi diversi possono accedervi.

Nota che quando esegui PHP come un’applicazione (Fast-)CGI nel tuo Web server, ogni processo PHP avrà la sua cache (i dati di APCu non sono condivisi tra i processi). In questi casi, potresti voler usare memcached, che non è legato ai processi PHP.

In una configurazione di rete APCu sarà generalmente più performante di memcached in termini di velocità di accesso, ma memcached potrà scalare meglio e più velocemente. Se non pensi di eseguire la tua applicazioni su server multipli, o non ti servono le funzionalità aggiuntive che memcached offre, allora APCu è probabilmente la scelta migliore per il caching degli oggetti.

Esempio di utilizzo con APCu:

<?php
// controlla se ci sono dati salvati come 'expensive_data' in cache
$data = apc_fetch('expensive_data');
if ($data === false) {
    // dati non in cache; salva il risultato per uso successivo
    apc_add('expensive_data', $data = get_expensive_data());
}

print_r($data);

Prima di PHP 5.5, APC fornisce sia una cache degli oggetti che una cache del bytecode. APCu è un progetto per portare la cache degli oggetti di APC a PHP 5.5 e successivi, dato che PHP Ora ha una cache del bytecode integrata (OPCache).

Impara a usare i sistemi di caching degli oggetti più famosi:

Torna su

Documentare il tuo codice

PHPDoc

PHPDoc è uno standard informale per i commenti al codice PHP. Ci sono molti tag diversi disponibili. La lista completa dei tag e degli esempi può essere trovata nel manuale di PHPDoc.

Qui sotto c’è un esempio di come potresti documentare una classe con alcuni metodi:

<?php
/**
 * @author Un Nome <un.nome@example.com>
 * @link http://www.phpdoc.org/docs/latest/index.html
 */
class DateTimeHelper
{
    /**
     * @param mixed $anything Qualunque cosa che si possa convertire in un oggetto \DateTime
     *
     * @throws \InvalidArgumentException
     *
     * @return \DateTime
     */
    public function dateTimeFromAnything($anything)
    {
        $type = gettype($anything);

        switch ($type) {
            // Del codice che prova a restituire un oggetto \DateTime
        }

        throw new \InvalidArgumentException(
            "Failed Converting param of type '{$type}' to DateTime object"
        );
    }

    /**
     * @param mixed $date Qualunque cosa che si possa convertire in un oggetto \DateTime
     *
     * @return void
     */
    public function printISO8601Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('c');
    }

    /**
     * @param mixed $date Qualunque cosa che si possa convertire in un oggetto \DateTime
     */
    public function printRFC2822Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('r');
    }
}

La documentazione della classe ha un tag @author e un tag @link. Il tag @author è usato per documentare l’autore del codice e può essere ripetuto per documentare più autori. Il tag @link è usato per linkare a un sito web che ha una relazione col codice.

Dentro la classe, il primo metodo ha un tag @param che documenta il tipo, il nome e la descrizione del parametro passato al metodo. Inoltre, ha dei tag @return e @throws che documentano rispettivamente il tipo restituito e qualunque eccezione che potrebbe essere lanciata.

Il secondo e il terzo metodo sono molto simili e hanno un solo tag @param come il primo metodo. La differenza importante nel secondo e terzo metodo è l’inclusione/esclusione del tag @return. @return void informa esplicitamente che non sarà restituito nulla; storicamente, omettere la dichiarazione @return void ha lo stesso significato (nessuna restituzione).

Torna su

Risorse

Ufficiali

Persone da seguire

Mentoring

Provider PaaS PHP

Framework

Piuttosto che reinventare la ruota, molti provider PHP usano dei framework per costruire le proprie applicazioni. I framework astraggono la maggior parte dei dettagli di basso livello e forniscono delle utili interfacce di semplice utilizzo per realizzare molte funzionalità comuni.

Non hai bisogno di un framework per ogni progetto. A volte il solo PHP è il modo giusto per realizzare le cose, ma se hai bisogno di un framework, ce ne sono tre tipi:

I micro-framework forniscono essenzialmente un modo per mappare una richiesta HTTP a un callback, un controller o un metodo il più velocemente possibile, e a volte forniscono alcune libreria extra per aiutare nello sviluppo come librerie di base per il database e cose del genere. Sono prevalentemente usati nella costruzione di servizi HTTP remoti.

Molti framework aggiungono un nome considerevole di funzionalità a quelle disponibili in un micro-framework; questi vengono detti framework completi. Di solito sono distribuiti con degli ORM, pacchetti per l’autenticazione etc.

I framework a componenti sono insiemi di librerie specializzate e con una sola responsabilità. Diversi framework a componenti possono essere usati insieme per creare un micro-framework o un framework completo.

Componenti

Come menzionato sopra, i componenti sono un altro approccio alla creazione, distribuzione e implementazione di codice condiviso. Esistono diversi repository di componenti; i due più famosi sono:

Entrambi questo repository hanno degli strumenti da linea di comando associati per aiutarti nel processo di installazione e aggiornamento, e sono stati spiegati in dettaglio nella sezione Gestione delle dipendenze.

Ci sono anche dei framework a componenti e provider componenti che non offrono alcun framework. Questi progetti forniscono solo un’altra sorgente di pacchetti che idealmente hanno poche o nessuna dipendenza verso altri pacchetti o framework specifici.

Per esempio, puoi usare il pacchetto Validation di FuelPHP senza dover usare il framework FuelPHP.

I componenti Illuminate di FuelPHP saranno meglio separati dal framework Laravel. Per ora, solo i componenti meglio separati sono elencati sopra.

Altre risorse utili

Cheatsheet

Altre pratiche raccomandate

L’universo PHP

Video tutorial

Canali Youtube

Video a pagamento

Libri

Ci sono un sacco di libri in giro su PHP, ma alcuni sono molto vecchi e non contengono più informazioni accurate. Ci sono anche libri pubblicati per “PHP 6” che non esiste, e non esisterà mai. La prossima versione di PHP sarà chiamata “PHP 7” per via di questi libri.

Questa sezione mira a essere un documento in costante aggiornamento sui libri raccomandati per lo sviluppo PHP in generale. Se vuoi che il tuo libro sia aggiunto, invia una PR e sarà presa in esame.

Libri gratuiti

Libri a pagamento

Torna su

Comunità

La comunità PHP è tanto diversificata quanto grande, e i suoi membri sono pronti e desiderosi di aiutare i nuovi programmatori PHP. Considera l’idea di entrare nel tuo gruppo PHP locale (PUG) o di partecipare a conferenze PHP più grandi per avere maggiori informazioni sulle pratiche qui descritte. Puoi passare nel canale IRC #phpc su irc.freenode.com e seguire l’account Twitter @phpc. Fatti vedere, incontra nuovi sviluppatori, impara nuove cose e, soprattutto, fai nuovi amici! Altre risorse della comunità includono la Comunità programmatori PHP su Google+ e StackOverflow.

Guarda il calendario ufficiale degli eventi PHP

PHP User Groups

If you live in a larger city, odds are there’s a PHP user group nearby. You can easily find your local PUG at the usergroup-list at php.net which is based upon PHP.ug. Alternate sources might be Meetup.com or a search for php user group near me using your favourite search engine (i.e. Google). If you live in a smaller town, there may not be a local PUG; if that’s the case, start one!

Special mention should be made of two global user groups: NomadPHP and PHPWomen. NomadPHP offers twice monthly online user group meetings with presentations by some of the top speakers in the PHP community. PHPWomen is a non-exclusive user group originally targeted towards the women in the PHP world. Membership is open to everyone who supports a more diverse community. PHPWomen provide a network for support, mentorship and education, and generally promote the creating of a “female friendly” and professional atmosphere.

Read about User Groups on the PHP Wiki

Conferenze PHP

La comunità PHP tiene anche delle conferenze regionali e nazionali in molti Paesi in tutto il mondo. A questi eventi parlano generalmente membri noti della comunità PHP, dunque è una buona opportunità per imparare direttamente dai leader del settore.

Trova una conferenza PHP

Torna su