Vai al contenuto

Conviene usare PHP al giorno d’oggi?

Nonostante per molti sia considerata obsoleta e persino odiata, pe quanto mi riguarda, utilizzerò per molti anni ancora la tecnologia PHP. A chi storce il naso su PHP, pongo sempre una semplice domanda: hai mai sviluppato in PHP?

Gran parte dei preconcetti su PHP risalgono alle versioni di PHP 4 e 5 quando il linguaggio era visto sempre più come una tecnologia “legacy”. Erano anche i tempi in cui venivano fuori i fantastici linguaggi di Ruby on Rails e Node.js. Il pensiero comune era che PHP fosse un linguaggio cattivo o almeno che la maggior parte della community utilizzava in maniera errata producendo migliaia di righe di codice errato: questo, in parte, è vero. Ma con l’arrivo di PHP 7 le cose sono cambiate e sono stati fatti grandi passi in avanti. Nel 2015 si è assistito all’inizio di una nuova era moderna di PHP. Venivano infatti introdotti, nuove funzionalità, tra cui:

  • notevoli miglioramenti delle prestazioni
  • un sistema di tipi notevolmente ampliato (tipi scalari e tipi restituiti)
  • classi anonime
  • l’operatore di coalescenza nullo ( ??)
  • unicode codepoint escape sintassi
  • e tanto altro ancora…

Negli ultimi anni, PHP è diventato un linguaggio significativamente più ergonomico, e, con l’arrivo di PHP 8, il linguaggio ha subito un ulteriore passo in avanti. Se siete curiosi, potete dare un’occhiata a questo articolo in cui vengono presentate alcune delle caratteristiche salienti.

Il sistema dei tipi di PHP

Con l’introduzione del sistema di tipi, il codice assume maggiore chiarezza. Nonostante non sia un sistema rigoroso come ad esempio Java, non si può considerare come un sistema del tutto opzionale come TypeScript. Php 8.1 ha un robusto sistema di tipi che include funzionalità come interfacce, tipi scalari e di oggetti, tipi nullable, tipi di unione e intersezione e molto altro. Diamo un occhiata a questo codice di esempio:

declare(strict_types=1);

class MyClass
{
    public \DateTimeInterface $dateTime = new \DateTime();

    public function __construct(public readonly LoggerInterface $logger)
    {
    }

    public function useUnionTypes(int|string $input): void
    {
        // il parametro $input può essere di tipo int o string
    } 
    
    public function useIntersectionTypes(Traversable&Countable $input): void 
    { 
        // il parametro $input deve soddisfare la condizione 'Traversable' AND 'Countable'
    }
}

Gestione dei pacchetti

Come i moderni linguaggi, anche PHP ha il suo gestore di pacchetti “ufficiale” da circa un decennio. Il suo nome è Composer ed è fortemente ispirato da altri gestori di pacchetti popolari, come npm per JavaScript. Packagist è il principale repository di pacchetti pubblico per Composer. Come npm, possiamo anche utilizzare Packagist per ospitare i nostri pacchetti privati ​​a un costo mensile ragionevole.

La principale differenza tra Composer e npm è in realtà una differenza culturale, più che tecnica: la comunità PHP generalmente non ha la preferenza per i micro-pacchetti come spesso accade su JavaScript, quindi è più probabile che il progetto PHP abbia dozzine di dipendenze più grandi rispetto a centinaia di dipendenze più piccole.

Frameworks

L’attuale panorama PHP è dominato dai due framework Laravel e Symfony. Entrambi sono framework moderni ed espressivi che mirano a rendere più facile scrivere applicazioni Web robuste, veloci e gestibili riducendo al contempo la scrittura del codice grazie all’uso di codice boilerplate. I framework potrebbero essere eccessivi per una webapp di modeste pretese? No, entrambi i framework possiedono una versione base (miniframework) che nel caso di Symfony equivale all’installazione base (skeleton) dove tutti i componenti stanno al di fuori del core e sono opzionali, mentre nel caso di Laravel, si avvale di una variante microframework chiamato Lumen.

Di seguito riporto un esempio di come potrebbe essere scritto un semplice script in PHP utilizzando il framework Symfony.

<?php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ExampleController
{
    // il parametro $randomNumberGenerator è automaticamente "iniettato" grazie a un servizio
    public function __construct( private RandomNumberGenerator $randomNumberGenerator ) {}

    #[Route('/number')] // da notare l'uso della notazione PHP introdotta in PHP 8 che è retrocompatibile con le vecchie versioni.
    public function number(): Response
    {
        $number = $this->randomNumberGenerator->generate(min: 1, max: 100) 
        return new Response( "<html><body>Your lucky number is: $number</body></html>" ); 
    }
}

L’ecosistema di PHP è open source

PHP ha un ecosistema open source incredibilmente robusto da far invidia anche a linguaggi più “rispettabili”.

Sono disponibili librerie open source di alta qualità e ben mantenute per tutto ciò di cui è probabile che l’applicazione PHP abbia bisogno. Quella che segue è una panoramica molto superficiale di alcuni dei pacchetti più significativi nell’ecosistema PHP:

  • pacchetti PHP popolari che rappresentano la base del framework Symfony
    • symfony/cache- una libreria di memorizzazione nella cache pronta per la produzione con supporto per molti archivi di supporto diversi
    • symfony/console- una libreria CLI
    • symfony/dependency-injection- un contenitore di servizio compatibile con PSR-11
    • symfony/dotenv- un gestione dei file .env
    • symfony/event-dispatcher- un dispacher di eventi
    • symfony/form- una libreria per la creazione e l’elaborazione di moduli (in HTML o altro)
    • symfony/http-client- una libreria client HTTP
    • symfony/mailer- una libreria multi-trasporto per la creazione e l’invio di email
    • symfony/messenger- un bus di messaggi con supporto per la sincronizzazione e l’elaborazione dei messaggi asincroni
    • symfony/notifier- uno strumento per l’invio di notifiche con supporto proprietario per e-mail, SMS, Slack, Discord, Telegram, notifiche push e altro
    • symfony/routing- il router utilizzato dal framework Symfony
    • symfony/security- utilità per l’autenticazione, l’autorizzazione, la protezione CSRF e altre esigenze di sicurezza
    • symfony/serializer- una libreria di serializzazione/deserializzazione con supporto per JSON, XML, YAML, CSV e altro
    • symfony/validator- una libreria di convalida dei dati
  • pacchetti del progetto The League of Extraordinary Packages, un insieme di pacchetti PHP moderni e conformi agli standard sviluppati con l’obiettivo di migliorare l’ecosistema PHP
    • league/commonmark- un parser Markdown conforme a CommonMark
    • league/csv- libreria per leggere e scrivere documenti CSV
    • league/flysystem- un’astrazione del filesystem con supporto per filesystem locali, storage di oggetti, FTP e altro
    • league/oauth2-server- un’implementazione del server di autorizzazione OAuth 2.0
    • league/oauth2-client- una libreria client OAuth 2.0 con supporto integrato e della community per molti provider OAuth 2.0 comuni, nonché provider personalizzati
    • league/omnipay- una libreria di elaborazione dei pagamenti multi-gateway
  • pacchetti del Progetto Doctrine, in gran parte ma non esclusivamente usati per la gestione dei database
    • doctrine/collections- utility per gestire array di dati
    • doctrine/dbal- libreria per il supporto ai database MySQL, Oracle, Microsoft SQL Server, PostgreSQL e SQLite
    • doctrine/orm- un popolare ORM basato sul modello Data Mapper
    • doctrine/migrations- utilità per il versionamento dello schema del database (es. migrazioni del database)
  • pacchetti del progetto PHPOffice, un insieme di librerie per lavorare con i formati di file prodotti da Microsoft Office e altre suite per l’ufficio
    • phpoffice/phppresentation- per leggere e scrivere formati di file di presentazione (es .pptx)
    • phpoffice/phpspreadsheet- per leggere e scrivere formati di file di fogli di calcolo (ad es .xlsx. , .csv)
    • phpoffice/phpword- per leggere e scrivere formati di file di documenti (es .docx)
  • guzzlehttp/guzzle- una libreria client HTTP basata su PSR-7
  • monolog/monolog- una libreria di registrazione molto utilizzata basata su PSR-3
  • phpunit/phpunit- il framework di test PHP standard de facto, basato sull’architettura xUnit
  • pestphp/pest- un moderno framework di test basato su PHPUnit
  • nesbot/carbon- un’estensione DateTime dell’API PHP
  • phpstan/phpstan- uno strumento di analisi statica, il più diffuso tra i numerosi progetti attivi
  • twig/twig- un motore di template, ispirato al motore di template Jinja di Python

PHP-FIG

Abbreviazione di “PHP Framework Interop Group” è un gruppo di sviluppo che ha lo scopo di standardizzare i concetti di programmazione di PHP, così come avviene con la Java Specification Request per Java. Lo scopo è di permettere l’interoperabilità dei componenti e fornire una base tecnica comune per l’implementazione di comprovate pratiche ottimali di programmazione e test. Il PHP-FIG è formato da alcuni fondatori del framework PHP. Il compito è quello di rilasciare le specifiche PSR, cioè  PHP Standard Recommendation.

Nel corso degli anni sono state rilasciate molte PSR utili e largamente utilizzate, tra cui:

  • uno standard di caricamento automatico ( PSR-4 )
  • interfacce per componenti app/framework comuni ( PSR-3 , PSR-6 , PSR-11 , PSR-14 , PSR-16 )
  • standard per gli oggetti di richiesta/risposta HTTP e il codice che li gestisce ( PSR-7 , PSR-18 )
  • guide di stile ( PSR-1 , PSR-12 )

Nessuna compilazione

Ovviamente, PHP è interpretato e non compilato. Questo significa che, rispetto a molti altri linguaggi, non è richiesto il passaggio di compilazione, né è richiesto di riavviare il server web quando cambiamo il tuo codice: basta salvare il codice, inviare la richiesta e la risposta ricevuta sarà quella interpretata dal nuovo codice appena salvato. Questo significa pure che per qualsiasi pacchetto installato tramite Composer (o utilizzato in altro modo) avremo la possibilità di vedere il codice sorgente effettivo, poiché appunto tutto il codice PHP non è compilato, ma interpretato al momento.

Vale la pena sottolineare che, nonostante non sia un linguaggio compilato, le ultime versioni (dalla 7 in poi) hanno dei benchmark paragonabili, se non addirittura migliori, dei linguaggi di pari livello come Ruby. Questi risultati sono dovuti al duro lavoro svolto nel corso degli anni dal team per migliorare le prestazioni PHP, fino all’aggiunta di funzionalità completamente nuove, come il compilatore JIT introdotto in PHP 8.