Salta ai contenuti

Impaginare una tabella HTML

Questa ricetta mostra come eseguire il rendering di una tabella HTML con intestazione, celle allineate, bordi e una riga a piè di pagina. Nella matrice di supporto CSS, le tabelle sono un modulo Verified. La ricetta segue examples/09-html-table.php.

Terminal window
composer require nextpdf/core:^3

Il vincolo si applica al pacchetto nextpdf/core. L’esempio viene eseguito con PHP 8.4.

Il motore HTML dispone di una pipeline dedicata per le tabelle (src/Html/Table/). TableParser raccoglie righe e celle in un buffer di breve durata; quindi la tabella viene impaginata e disegnata. È l’unica deviazione riconosciuta dal modello no-retained-DOM in ADR-001. Il buffer è di breve durata ed è limitato al proprio contenitore. Non è un DOM persistente.

Le larghezze delle colonne seguono il modello CSS Table. La tabella viene impaginata con una specifica larghezza utilizzata; quindi l’algoritmo di dimensionamento delle colonne determina la larghezza utilizzata di ciascuna colonna (W3C CSS Table Level 3). Con table-layout: fixed, il contenuto delle celle viene ignorato nel calcolo della larghezza. A determinare il layout sono invece la prima riga e le larghezze esplicite delle colonne (W3C CSS Table Level 3).

Nella matrice, CSS Table Level 3 è classificato come Verified. Questa classificazione è supportata da quattro fonti: src/Html/Table/, la suite di unit test per Table, i test di TableParser e i golden PDF sintetici.

Il rendering delle tabelle avviene tramite writeHtml(string $html): static (NextPDF\Core\Concerns\HasTextOutput). Il motore supporta il markup standard delle tabelle. I tag supportati sono table, thead, tbody, tfoot, tr, th e td. Gli attributi supportati sono border, cellpadding, cellspacing, colspan e l’attributo style per cella. La tabella PHPDoc completa viene generata a partire dal codice sorgente.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->writeHtml(
'<table border="1" cellpadding="5"><tr><th>SKU</th><th>Qty</th></tr>'
. '<tr><td>NPD-CORE</td><td style="text-align: right;">1</td></tr></table>'
);
$doc->save(__DIR__ . '/out.pdf');

Questo esempio è autonomo ed eseguibile dall’harness. Rispecchia examples/09-html-table.php e mostra un’intestazione con stile, sfondi di riga alternati, colonne numeriche allineate e un totale a piè di pagina.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('HTML Table');
$doc->addPage();
$html = <<<'HTML'
<h1 style="color: #1E3A8A;">Product Inventory Report</h1>
<table border="1" cellpadding="5" cellspacing="0" style="width: 100%;">
<thead>
<tr style="background-color: #1E3A8A; color: #FFFFFF;">
<th style="width: 10%;">#</th>
<th style="width: 45%;">Product</th>
<th style="width: 20%; text-align: center;">SKU</th>
<th style="width: 25%; text-align: right;">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>NextPDF Core License</td>
<td style="text-align: center;">NPD-CORE</td>
<td style="text-align: right;">$0.00</td>
</tr>
<tr style="background-color: #F8FAFC;">
<td>2</td>
<td>NextPDF Pro License</td>
<td style="text-align: center;">NPD-PRO</td>
<td style="text-align: right;">$299.00</td>
</tr>
</tbody>
<tfoot>
<tr style="background-color: #1E293B; color: #FFFFFF; font-weight: bold;">
<td colspan="3" style="text-align: right;">Grand total:</td>
<td style="text-align: right;">$299.00</td>
</tr>
</tfoot>
</table>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/html-table-layout.pdf');
echo "Wrote html-table-layout.pdf\n";

STDOUT previsto:

Wrote html-table-layout.pdf
  • Larghezze percentuali. Le percentuali di width delle colonne vengono risolte rispetto alla larghezza utilizzata della tabella. L’algoritmo di dimensionamento delle colonne normalizza le percentuali la cui somma non è 100. Non presupporre larghezze esatte in pixel.
  • colspan. Una cella che si estende su più colonne partecipa alla ripartizione della larghezza tra le colonne che occupa. Un totale a piè di pagina che si estende sulla maggior parte delle colonne è uno schema comune e supportato.
  • Modello dei bordi. In alcune fixture per tabelle, il valore predefinito di border-collapse differisce dal valore iniziale CSS. Impostarlo esplicitamente quando il rendering dei bordi è importante.
  • Rowspan attraverso le interruzioni di pagina. Una cella con rowspan può attraversare il limite di una pagina; in tal caso il paginatore rowspan frammenta quella cella (ADR-007). Una cella molto alta che non può essere suddivisa può generare UnsplittableContentException.
  • Celle vuote. Un <td> vuoto occupa comunque la propria posizione nella griglia. Non viene compresso.

Il buffer della tabella è di breve durata ed è limitato al proprio contenitore. I costi del parsing sono lineari rispetto al numero di celle, oltre al passaggio di dimensionamento delle colonne a O(rows x cols). Il budget è wall_ms: 1500, peak_mb: 96. Mantenere una singola tabella entro il limite di nodi ADR-020 di 5,000 nodi per contesto.

Estratto della matrice di supporto CSS (solo righe Verified)

Sezione intitolata “Estratto della matrice di supporto CSS (solo righe Verified)”

Questo estratto riproduce solo le righe Verified della matrice di supporto CSS sottoposta a verifica dei fatti.

Modulo W3CLivelloStatoEvidenza
CSS Table (css_tables_3)3Verifiedsrc/Html/Table/, tests/Unit/Html/Table/ + test di TableParser + golden PDF
CSS Flexible Box Layout (css_flexbox_1)1Verifiedsrc/Html/Flex/, tests/Unit/Html/Flex/
CSS Grid Layout (css_grid_1)1Verifiedsrc/Html/Grid/, corpus WPT
CSS Cascading and Inheritance (css_cascade_3)3Verifiedsrc/Html/Cascade/

background-color, usato qui per alternare i colori delle righe, è classificato come «Claimed» nella matrice. Secondo l’audit della Fase 0, il suo ambito è la cella della tabella. Viene renderizzato sulle righe della tabella, ma non è elencato come Verified.

Vincoli dello streaming a passaggio singolo (ADR-001)

Sezione intitolata “Vincoli dello streaming a passaggio singolo (ADR-001)”

Il buffer della tabella è l’eccezione documentata al modello di streaming. È di breve durata e delimitato; non è un DOM generale. Non fare affidamento su una tabella per fornire un contesto ad albero ai contenuti esterni alla tabella.

FormattingContextFactory::startTable() legge il CSS tramite il contratto del livello di layout. Non analizza il $css[...] grezzo durante il dispatch. La superficie pubblica resta writeHtml().

Budget di memoria per documenti di grandi dimensioni

Sezione intitolata “Budget di memoria per documenti di grandi dimensioni”

Un contesto di formattazione della tabella è limitato a 5,000 nodi e a 20 livelli di profondità, entro il limite massimo di memoria attiva di 50 MB (ADR-020). Suddividere o impaginare una tabella molto grande. Non eseguirne il rendering come singolo contesto di dimensioni eccessive.

Il markup di tabella proveniente da input non attendibile è soggetto agli stessi limiti sugli elementi e sull’annidamento applicati al resto dell’HTML. Convalidare i dati della tabella assemblati da un utente. Il renderer non esegue il contenuto e, con i criteri predefiniti, non recupera risorse remote arbitrarie.

DichiarazioneSpecificaClausolareference_id
Le larghezze utilizzate delle colonne vengono determinate dall’algoritmo di dimensionamento delle colonne della tabella alla larghezza utilizzata della tabella.W3C CSS Table Level 3css_tables_3#x1.x4.x9.x3
In modalità fixed, il contenuto delle celle viene ignorato nel calcolo della larghezza delle colonne.W3C CSS Table Level 3css_tables_3#x1.x4.x5.x1.p6

Questa ricetta mostra come NextPDF esegue il rendering delle tabelle HTML supportate. CSS Table Level 3 è Verified nella matrice di supporto e gli altri moduli CSS usati qui sono classificati in base a tale matrice.

Non applicabile.