PHP 8.4: le novità della nuova versione


PHP ha visto una notevole evoluzione dalla sua nascita, con ogni versione che introduce miglioramenti per renderlo più potente.
Gli aggiornamenti di versione minor, come PHP 8.4, portano un mix di nuove funzionalità.
In questo articolo esploreremo le aggiunte più importanti di PHP 8.4.

Property Hooks

I Property Hooks rappresentano una delle novità principali introdotte in PHP 8.4. Questa funzionalità consente agli sviluppatori di definire comportamenti personalizzati per la lettura e la scrittura delle proprietà di una classe, eliminando la necessità di usare metodi getter e setter tradizionali o metodi magici come __get() e __set().

Come funzionano i Property Hooks?

Con i Property Hooks, è possibile aggiungere logica personalizzata direttamente sulle proprietà usando le parole chiave get e set. Di seguito un esempio pratico:


class Locale {
    public string $languageCode;

    public string $countryCode {
        set (string $countryCode) {
            $this->countryCode = strtoupper($countryCode);
        }
    }

    public string $combinedCode {
        get => sprintf("%s_%s", $this->languageCode, $this->countryCode);
        set (string $value) {
            [$this->languageCode, $this->countryCode] = explode('_', $value, 2);
        }
    }
}

$brazilianPortuguese = new Locale('pt', 'br');
echo $brazilianPortuguese->countryCode; // Output: BR
echo $brazilianPortuguese->combinedCode; // Output: pt_BR

Questo esempio mostra come personalizzare la scrittura di una proprietà per convertirne il valore in maiuscolo e come generare una proprietà virtuale combinando più valori.

Vantaggi rispetto alle versioni precedenti

Nelle versioni precedenti, per ottenere una funzionalità simile, era necessario ricorrere a metodi magici o a getter e setter separati. Ad esempio:


class User_OLD {
    private string $_name;

    public function __get(string $propName): mixed {
        return match ($propName) {
            'name' => $this->_name,
            default => throw new Error("Undefined property $propName"),
        };
    }

    public function __set(string $propName, $value): void {
        if ($propName === 'name' && strlen($value) === 0) {
            throw new ValueError("Name cannot be empty");
        }
        $this->_name = $value;
    }
}

Con i Property Hooks, la sintassi è più semplice e leggibile:


class User {
    public string $name {
        set {
            if (strlen($value) === 0) throw new ValueError("Name cannot be empty");
            $this->name = $value;
        }
    }
}

Possibili utilizzi

Alcuni casi d’uso pratici per i Property Hooks includono:

  • Validazione dei dati prima della scrittura
  • Proprietà virtuali calcolate
  • Conversione automatica di formati o unità

Visibilità asimmetrica delle proprietà

PHP 8.4 introduce il supporto per la visibilità asimmetrica delle proprietà, permettendo livelli di accesso differenti per la lettura (get) e la scrittura (set).
Questa funzionalità semplifica scenari in cui le proprietà necessitano di accesso pubblico in lettura ma limitato in scrittura.
Documentazione ufficiale.


class Esempio {
    public protected(set) string $nome;

    public function __construct(string $nome) {
        $this->nome = $nome;
    }
}

Attributo #[\Deprecated]

L’attributo #[\Deprecated] standardizza il modo in cui gli sviluppatori possono contrassegnare metodi, funzioni o costanti come deprecati.
Fornisce un messaggio strutturato per gli avvisi di deprecazione.
Documentazione ufficiale.


class Esempio {
    #[\Deprecated(message: "Usa il metodo newMethod() invece", since: "8.4")]
    public function oldMethod() {
        // Vecchia implementazione
    }

    public function newMethod() {
        // Nuova implementazione
    }
}

Miglioramenti al DOM API con supporto per HTML5

L’estensione DOM ora supporta la gestione di documenti HTML5 con nuove classi standardizzate nel namespace Dom.
Questo aggiornamento risolve problemi di conformità e semplifica la manipolazione degli HTML.
Documentazione ufficiale.


$html = '<main><article>Contenuto</article></main>';
$dom = Dom\HTMLDocument::createFromString($html);

$nodo = $dom->querySelector('main > article');
echo $nodo->textContent; // Output: "Contenuto"

API orientata agli oggetti per BcMath

Il nuovo oggetto BcMath\Number consente un approccio orientato agli oggetti per operazioni aritmetiche ad alta precisione.
Supporta operatori standard e implementa l’interfaccia Stringable per i contesti stringa.
Documentazione ufficiale.


use BcMath\Number;

$num1 = new Number('0.12345');
$num2 = new Number('2');
$risultato = $num1 + $num2;

echo $risultato; // Output: "2.12345"

Nuove funzioni per gli array

PHP 8.4 introduce nuove funzioni per la gestione degli array, tra cui:

  • array_find(): Trova il primo elemento corrispondente.
  • array_find_key(): Trova la chiave del primo elemento corrispondente.
  • array_any(): Verifica se un elemento corrisponde a una condizione.
  • array_all(): Verifica se tutti gli elementi corrispondono a una condizione.

Documentazione ufficiale.

Sottoclassi specifiche per driver PDO

Le sottoclassi specifiche per i driver PDO (ad esempio, Pdo\MySql, Pdo\Sqlite) permettono metodi specifici per i driver.
Documentazione ufficiale.

Chiamata ai metodi senza parentesi

PHP 8.4 permette la chiamata ai metodi senza parentesi se non richiedono argomenti obbligatori.
Documentazione ufficiale.


class Esempio {
    public function versione(): string {
        return "8.4";
    }
}

$esempio = new Esempio();
echo $esempio->versione; // Output: "8.4"

PHP 8.1: le novità della nuova versione

Introduzione

PHP prosegue con il suo avanzamento attraverso versioni Minor con PHP 8.1 rilasciato a novembre 2021. Questa versione include caratteristiche significative, tra cui Enumerazioni, Fibers, e molto altro.

1. Enumerazioni (Enums)

Una delle caratteristiche più attese in PHP 8.1 sono le Enumerazioni (Enums). Gli Enums permettono di definire una serie di valori costanti e gestire variabili che possono contenere solo uno di questi valori, migliorando la robustezza del codice.

Il tipo enum è rappresentato internamente come una classe.
Le enumerazioni sono oggetti e hanno: una proprietà ‘name’ che è il nome enumerazione.
Le enumerazioni possono essere associate ad uno scalare es una stringa ad esempio allo scopo di essere salvata in un database.
Le enumerazioni associate a uno scalare es una stringa hanno anche la proprietà ‘value’


enum Status: string {
    case Active = 'active';
    case Inactive = 'inactive';
    case Archived = 'archived';
}

function setStatus(Status $status) {
    // Gestisce lo stato
}
setStatus(Status::Active);
setStatus(Status::Inactive);

echo Status::Active->name; // prints "Active"
echo Status::Active->value; // prints "active"

2. Fibers

Le Fibers sono un’implementazione di primitive di concorrenza. Esse sono di aiuto per la programmazione asincrona in PHP. Consentono tra l’altro di semplificare il codice delle Promise o le coroutine di Generator, e la sospensione e la ripresa di funzioni asincrone.


$fiber = new Fiber(function(): void {
    echo "Fiber in esecuzione";
    Fiber::suspend();
    echo "Fiber ripreso";
});

$fiber->start();
echo "Codice principale";
$fiber->resume();


$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];

3. Intersezione dei Tipi (Intersection Types)

Gli Intersection Types permettono di richiedere che un parametro appartenga a più di un tipo allo stesso tempo. È particolarmente utile quando si lavora con interfacce.


function processData(A & B $data) {
    // Funzione che richiede oggetti che implementano sia A che B
}

4. Readonly Properties

Le proprietà di sola lettura non possono essere modificate dopo l’inizializzazione, ovvero dopo che è stato loro assegnato un valore.


class User {
public readonly string $username;
public function __construct(string $username) {
$this->username = $username;
}
}
$user = new User("Biagio");
// $user->username = "NuovoNome"; // Questo genererebbe un errore

4. Array is_list

La nuova funzione array_is_list consente di verificare se un array è una lista, cioè se ha chiavi sequenziali partendo da 0.


$result = array_is_list(['a', 'b', 'c']); // true

5. Performance Improvements

PHP 8.1 introduce vari miglioramenti di performance, inclusi quelli per le opcache e la gestione della memoria. Questo rende PHP 8.1 ancora più veloce e reattivo, specialmente per applicazioni su larga scala.

Conclusione

PHP 8.1 continua a potenziare il linguaggio, offrendo miglioramenti sia nelle funzionalità che nelle performance. Le nuove funzioni come Enums e Fibers aprono nuove strade per lo sviluppo in PHP, permettendo di scrivere codice più robusto e flessibile.

Riferimenti Utili

PHP 8.3: le novità della nuova versione

Introduzione

Le versioni Minor di PHP, come PHP 8.3, introducono miglioramenti e funzionalità.

1. Aggiunta dei Typed Class Constants

PHP 8.3 introduce i Typed Class Constants, permettendo ai programmatori di dichiarare costanti di classe tipizzate.


class Example {
    public const string NAME = 'Esempio';
}



interface I {
    const string PHP = 'PHP 8.1';
}

class Bar83 implements I {
    const string PHP = 'PHP 8.3';
}
echo 'Bar83::PHP: ' . Bar83::PHP; //print 'PHP 8.3'

class FooPHPArr implements I {
    const string PHP = []; // Fatal error: Cannot use array as value for class constant FooPHPArr::PHP of type string
}

2. Attributo #[\Override]

Con l’aggiunta dell’attributo #[\Override] a un metodo, PHP si assicura che esista un metodo con lo stesso nome in una classe genitore o in un’interfaccia implementata. Questa funzionalità rende sia piu leggibile il codice che semplificato il refactoring in quanto verrà rilevata la rimozione o il rename di un metodo sovrascritto.


//classe padre
class TestCase {

    protected function setUp(): void {
    }

    protected function tearDown(): void {
    }
}

/*

PHP < 8.3

final class MyTest extends TestCase {
    protected $logFile;

    protected function setUp(): void {
        $this->logFile = fopen('/tmp/logfile', 'w');
    }

    protected function taerDown(): void {
        fclose($this->logFile);
        unlink('/tmp/logfile');
    }
}

// The log file will never be removed, because the
// method name was mistyped (taerDown vs tearDown).

*/

//PHP 8.3

final class MyTest extends TestCase {
    protected $logFile;

    #[\Override]
    protected function setUp(): void {
        $this->logFile = fopen('/tmp/logfile', 'w');
    }

    #[\Override]
    //protected function taerDown(): void {
    protected function tearDown(): void {
        fclose($this->logFile);
        unlink('/tmp/logfile');
    }
}
// PHP Fatal error:  MyTest::taerDown() has #[\Override] attribute, but no matching parent method exists

3. funzione json_validate()

la funzione json_validate() verifica se una stringa è un JSON valido.



var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true


4. nuovi metodi di Randomizer

La Random Extension introdotta nelle versioni precedentei, con PHP 8.3 viene arricchita di nuovi metodi.

Il metodo getBytesFromString restituisce una sringa causale di caratteri estratti dalla stringa di caratteri passata come argomento.


$randomizer = new \Random\Randomizer();
printf(
    "%s.example.com",
    $randomizer->getBytesFromString('abcdefghijklmnopqrstuvwxyz0123456789', 16)
);
output something similar to:
3zsw04eiubcf82jd.example.com

Il metodo getFloat(float $min, float $max, Random\IntervalBoundary $boundary = Random\IntervalBoundary::ClosedOpen): float
restituisce un numero float casuale, quanto piu possibile uniformemente distribuito dall intervallo ($min, $max).


Generate a random latitude and longitude:
$randomizer = new \Random\Randomizer();
// Note that the latitude granularity is double the
// longitude's granularity.
//
// For the latitude the value may be both -90 and 90.
// For the longitude the value may be 180, but not -180, because
// -180 and 180 refer to the same longitude. ???
var_dump(sprintf(
    "Lat: %+.6f Lng: %+.6f",
    $randomizer->getFloat(-90, 90, \Random\IntervalBoundary::ClosedClosed),
    $randomizer->getFloat(-180, 180, \Random\IntervalBoundary::OpenClosed),
)); // string(32) "Lat: -51.742529 Lng: +135.396328"



Il metodo nextFloat(): float
restituisce un numero float casuale, quanto piu possibile uniformemente distribuito dall’intervallo semiaperto [0, 1).


$r = new \Random\Randomizer();
print $r->nextFloat();

Riferimenti Utili