Salta ai contenuti
getnextpdf.com

Le basi di PHP 8.4

Spec: ISO 32000-2, §7.5.2Vincolo PHP: ≥8.4 <9.0

NextPDF richiede PHP 8.4. Questa pagina spiega su quali funzionalità del linguaggio 8.4 il motore fa davvero affidamento, perché quella versione è un limite minimo rigido e non un semplice suggerimento, e in che modo una build di downgrade separata mantiene aperta la possibilità di eseguire il codice su runtime meno recenti senza indebolire il codice che si legge.

Un motore PDF trasforma input ambiguo in un formato di file definito byte per byte. PDF è un formato consolidato da tempo, con regole solide e fisse, ed è abbastanza rigido da rendere costosa qualsiasi ipotesi errata. Il linguaggio in cui è scritto il motore è il primo punto in cui quelle ipotesi vengono intercettate oppure lasciate passare senza controllo. Un limite minimo di versione non è una restrizione fine a sé stessa. È la linea sotto la quale il motore non può più offrire le garanzie di tipo da cui dipende il resto della sua progettazione.

Se quel limite minimo è vago, i costi sono due. Il codice si riempie di adattatori di compatibilità che oscurano la logica reale. Anche il sistema di tipi smette di essere portante, ed è esattamente la proprietà che un flusso documentale non può permettersi di perdere.

  • Il pacchetto core dichiara "php": ">=8.4 <9.0". Questo è il vincolo reale, verificato in composer.json, non un’aspirazione documentale.
  • 8.4 è il limite minimo perché il motore usa le funzionalità del linguaggio 8.4 (e delle 8.x recenti) come garanzie strutturali: visibilità asimmetrica, enum con valore di base dotati di comportamento, costanti di classe tipizzate, stato readonly e argomenti con nome di prima classe nell’API pubblica.
  • L’esecuzione su PHP 8.1–8.3 è comunque possibile tramite una build di downgrade separata (il backport). È strumentazione di build, non una dipendenza di runtime. Non modifica il codice che si legge nel repository core.
  • Il limite superiore <9.0 è deliberato: una nuova release major di PHP è trattata come qualcosa da convalidare, non da dare per scontato.

Il limite minimo è stabilito da ciò che il codice fa. Per questo il modo più trasparente per spiegarlo è mostrare le funzionalità nel codice anziché elencarle in astratto.

La visibilità asimmetrica consente di rendere lo stato leggibile pubblicamente ma scrivibile solo privatamente, senza dover scrivere un getter a mano per ogni campo. Il contesto di rendering la usa direttamente:

declare(strict_types=1);
final class RenderingContext
{
// Readable everywhere, writable only inside the class.
public private(set) float $x = 0.0;
public private(set) float $y = 0.0;
public private(set) int $currentPageIndex = -1;
public private(set) string $currentContentStream = '';
}

Da sola, questa funzionalità del linguaggio elimina un’intera categoria di mutazioni esterne accidentali. Il cursore non può essere spostato dall’esterno del motore. La garanzia è imposta dal runtime, non da una convenzione che i revisori devono ricordarsi di applicare.

Gli enum con valore di base dotati di comportamento sostituiscono flag booleani sparsi e costanti stringa con un unico valore tipizzato che risponde anche a domande su sé stesso. Il discriminatore di conformità del documento è un enum con valore di base i cui metodi guidano decisioni a livello di specifica:

declare(strict_types=1);
enum ConformanceMode: string
{
case Plain = 'plain';
case PdfUa2 = 'pdfua2';
case PdfA4 = 'pdfa4';
case PdfA4f = 'pdfa4f';
public function isTagged(): bool
{
return match ($this) {
self::Plain => false,
default => true,
};
}
/** @return 2|3|4|null */
public function pdfaPart(): ?int
{
return match ($this) {
self::PdfA4, self::PdfA4f => 4,
default => null,
};
}
}

L’enum è l’unica fonte di verità per stabilire «questo documento è etichettato secondo la specifica?» e «quale parte ISO si applica?». Quando quelle domande erano espresse come booleani slegati, più punti potevano rispondervi in modo incoerente.

Le costanti di classe tipizzate rendono anche le costanti parte del contratto di tipo. I limiti rigidi del motore HTML sono dichiarati come costanti tipizzate:

private const int MAX_NESTING_DEPTH = 100;
private const int MAX_ELEMENT_COUNT = 50_000;

Gli argomenti con nome fanno parte della superficie dell’API pubblica, non sono un espediente interno. I programmi di esempio li usano in punti di chiamata che il lettore è invitato a copiare:

$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);

Non si tratta di usi decorativi della nuova sintassi. Ciascuno trasforma una convenzione che un revisore dovrebbe altrimenti imporre a mano in una proprietà imposta dal runtime.

Il più piccolo programma corretto mette già alla prova il limite minimo. Funziona su PHP 8.4, usa un argomento con nome e produce un file conforme:

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Hello World');
$doc->addPage();
$doc->setFont('helvetica', '', 24);
$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);
$doc->save(__DIR__ . '/hello.pdf');

Qui non c’è nulla di esotico. Il punto è che le stesse scelte di tipizzazione rigorosa, enum e visibilità asimmetrica che rendono affidabili gli interni del motore sono già attive alla base di questo programma di cinque righe. Non occorre attivarle esplicitamente.

L’interpretazione errata più comune è che «richiede PHP 8.4» significhi «non funzionerà se non si aggiorna a 8.4». Significa che il sorgente core ha come destinazione 8.4. Esiste una build di downgrade separata per i team vincolati a PHP 8.1–8.3.

È importante essere precisi su cosa sia quella build. È un flusso di downgrade basato su Rector che trasforma il sorgente 8.4 in output con sintassi più datata. È infrastruttura di build, non una libreria di runtime da aggiungere alle dipendenze della propria applicazione. Non introduce codice parallelo con tipizzazione più debole. Il codice esaminato in queste pagine e il codice distribuito sono lo stesso codice. Il backport è una trasformazione applicata a esso, non un’alternativa a esso.

Questa pagina spiega perché 8.4 è il limite minimo e cosa preserva il backport. Non documenta come eseguire il flusso di downgrade, le versioni di destinazione supportate o i suoi avvertimenti operativi. Questi aspetti appartengono alla documentazione specifica della build di backport. La struttura interna dei pacchetti di quella strumentazione è fuori dall’ambito di questa pagina. Gli usi delle funzionalità mostrati sono indicativi dello stile del motore. Non costituiscono l’inventario completo di ogni funzionalità 8.x che il codice utilizza. Le API esatte sono definite dal riferimento, non da questa spiegazione. Il vincolo di versione è accurato alla data di revisione di questa pagina. Il valore di riferimento è sempre il blocco require nel composer.json del core.

L’edizione non incide sul limite minimo del linguaggio. Ogni edizione è costruita dallo stesso sorgente PHP 8.4:

PHP 8.4 source floor — edition availability
EditionAvailability
CoreIl core è scritto per PHP 8.4.
ProPro usa lo stesso limite minimo del sorgente 8.4.
EnterpriseEnterprise usa lo stesso limite minimo del sorgente 8.4.
  • Limite minimo di versione — la versione minima di PHP a cui punta il sorgente core (>=8.4). Sotto tale limite, le garanzie di tipo del motore non possono essere espresse.
  • Visibilità asimmetrica — una funzionalità di PHP 8.4 che consente a una proprietà di essere leggibile pubblicamente ma scrivibile solo da uno scope più ristretto (public private(set)).
  • Enum con valore di base — un enum PHP i cui casi hanno valori scalari e che può contenere comportamento (metodi), usato qui come unica fonte di verità tipizzata.
  • Backport — la build di downgrade separata basata su Rector che trasforma il sorgente 8.4 in output eseguibile su runtime PHP meno recenti. Strumentazione di build, non una dipendenza di runtime.
  • Modalità di conformità — il discriminatore tipizzato del motore per stabilire quale contratto di conformità ISO un documento deve soddisfare.