I blocchi hanno la reputazione di essere complicati. Troppi file di configurazione, troppi tutorial del 2019, troppa magia npm. Ma è ancora così? In questo tutorial ti mostro che il percorso da una cartella vuota a un Dynamic Block funzionante richiede circa 5 minuti. Nessuna conoscenza pregressa, nessun file di configurazione infinito: solo l’essenziale per iniziare subito.
Perché è importante adesso
C’è un altro motivo per cui vale la pena capire le basi. Se hai usato strumenti AI per generare blocchi, avrai notato che usano tutti lo stesso tooling: create-block, wp-scripts, block.json, render.php. Anche se un LLM scrive il codice al posto tuo, devi comunque capire cosa sta facendo. Ed è esattamente lo scopo di questo corso.
Cos’è un Dynamic Block?
Un Static Block salva il suo output HTML direttamente nel database. Quello che si vede nell’editor è esattamente quello che viene memorizzato.
Un Dynamic Block funziona diversamente. Salva solo gli attributi, cioè le impostazioni configurate dall’utente. L’HTML effettivo viene generato da PHP a ogni caricamento della pagina. L’output è sempre aggiornato.
Nessun save.js necessario. Solo un file render.php. Per la maggior parte dei casi d’uso reali, è esattamente quello che serve.
| Aspetto | Static Block | Dynamic Block |
|---|---|---|
| Output | HTML salvato nel database | Renderizzato da PHP a ogni richiesta |
save.js | Necessario | Non utilizzato |
render.php | Non utilizzato | Necessario |
| Caso d’uso | Contenuto fisso | Dati live/calcolati |
Scaffolding: tre comandi e via
WordPress fornisce uno strumento ufficiale di scaffolding: create-block. Tre comandi, e si ottiene un plugin blocco funzionante con un setup di build moderno:
npx @wordpress/create-block@latest my-block --variant=dynamic
cd my-block
npm start
Nessuna configurazione Webpack, tutto è gestito da wp-scripts.
Alcune opzioni del comando
| Flag | Descrizione |
|---|---|
--variant=dynamic | Crea un blocco dinamico (con render.php) |
--namespace=my-namespace | Namespace personalizzato |
--wp-env | Include wp-env per un ambiente Docker locale |
--no-plugin | Crea solo i file del blocco, senza wrapper plugin |
I quattro file che contano
Dopo lo scaffolding, la struttura del plugin si presenta così:
my-block/
├── block.json # Definizione e metadati del blocco
├── src/
│ ├── index.js # Registrazione lato client
│ ├── edit.js # Componente UI per l'editor
│ ├── editor.scss # Stili editor (opzionale)
│ └── style.scss # Stili frontend (opzionale)
├── build/ # Output compilato (generato)
│ ├── index.js
│ ├── index.css
│ └── render.php
├── my-block.php # File principale del plugin
└── package.json # Dipendenze npm e script
I quattro file fondamentali:
block.json è il manifesto, la fonte di verità del blocco.index.js registra il blocco lato client.edit.js è un componente React che controlla l’aspetto del blocco nell’editor.render.php è dove avviene la magia sul frontend: rendering server-side con PHP.
block.json: il manifesto del blocco
Per i Dynamic Block, il campo più importante è render:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-namespace/my-block",
"version": "0.1.0",
"title": "My Dynamic Block",
"category": "widgets",
"icon": "smiley",
"description": "Un blocco con rendering dinamico server-side.",
"supports": {
"html": false
},
"textdomain": "my-block",
"editorScript": "file:./index.js",
"render": "file:./render.php"
}
La riga che fa la differenza
"render": "file:./render.php"
Questa singola riga dice a WordPress: non cercare una funzione save in JavaScript, renderizza questo blocco con PHP. È l’intera differenza tra un blocco statico e uno dinamico.
index.js: registrazione lato client
import Edit from './edit';
import metadata from './block.json';
registerBlockType(metadata.name, {
edit: Edit,
});
Cosa fa: importa i metadati da block.json, importa il componente Edit, e chiama registerBlockType(). Non c’è nessuna proprietà save, perché il rendering è gestito da render.php.
edit.js: React nell’editor
Il file edit.js è un componente React. Tre cose da ricordare:
useBlockProps(): va sempre applicato con spread sull’elemento root. È il modo in cui WordPress applica classi e stili corretti.InspectorControls: per aggiungere un pannello di impostazioni nella sidebar.setAttributes(): da chiamare ogni volta che l’utente modifica qualcosa.
Questo è il pattern. Una volta visto, si può costruire qualsiasi UI per l’editor.
render.php: sempre aggiornato
Il file render.php viene eseguito a ogni caricamento della pagina. Tre cose da sapere:
$attributes: contiene tutto ciò che l’utente ha configurato nell’editor.get_block_wrapper_attributes(): genera il markup wrapper corretto. Da usare sempre.esc_html(): per fare l’escape dell’output. Sempre.
<?php
/**
* PHP file to use when rendering the block.
*/
?>
<p <?php echo get_block_wrapper_attributes(); ?>>
<?php echo esc_html( $attributes['message'] ?? 'Hello World' ); ?>
</p>
Block Supports: non costruire ciò che WordPress ti dà gratis
Invece di costruire color picker, font size control e spacing UI personalizzati, basta dichiarare nella block.json quello che serve:
"supports": {
"color": {
"text": true,
"background": true
},
"typography": {
"fontSize": true,
"lineHeight": true
},
"spacing": {
"margin": true,
"padding": true
}
}
WordPress genera i controlli nell’editor e applica gli stili nel frontend automaticamente, nell’editor e nel frontend.
Cosa offre ogni Block Support?
Color: color picker per testo e sfondo, verifica contrasto.
Typography: selettore dimensione font, controllo altezza riga.
Spacing: controlli per margine e padding.
L’elenco dei block support è in continua crescita. Per una panoramica completa e aggiornata, consultare la documentazione ufficiale dei Block Supports.
Attributi: la memoria del blocco
Gli attributi definiscono i dati che un blocco memorizza. Si definiscono nella block.json:
"attributes": {
"message": {
"type": "string",
"default": "Hello World"
},
"count": {
"type": "integer",
"default": 0
},
"isVisible": {
"type": "boolean",
"default": true
},
"items": {
"type": "array",
"default": []
}
}
Tipi disponibili
| Tipo | Descrizione | Esempio |
|---|---|---|
string | Valori testuali | "Hello" |
boolean | Vero/falso | true |
integer | Numeri interi | 42 |
number | Come integer | 3.14 |
array | Lista di valori | ["a", "b"] |
object | Coppie chiave-valore | {"key": "val"} |
enum | Set fisso di valori | "small" |
Per i Dynamic Block, gli attributi vengono passati automaticamente a render.php. Non serve collegare nulla manualmente.
Workflow di sviluppo
Due comandi per il lavoro quotidiano:
# Sviluppo (watch mode + hot reload)
npm start
# Build per la produzione
npm run build
Alcuni script disponibili
| Script | Scopo |
|---|---|
npm start | Server di sviluppo con hot reload |
npm run build | Build di produzione |
npm run format | Formattazione con Prettier |
npm run lint:js | Lint JavaScript/TypeScript |
npm run lint:css | Lint CSS/SCSS |
Tutto è alimentato da @wordpress/scripts. Zero configurazione.
Ambiente di sviluppo locale
Per un ambiente Docker locale, si può includere wp-env:
npx @wordpress/create-block@latest my-block --variant=dynamic --wp-env
npm run wp-env start
Il blocco sarà disponibile su http://localhost:8888.
Blocchi solo PHP
Si può registrare un blocco interamente in PHP, senza JavaScript:
register_block_type('my-plugin/server-block', [
'attributes' => [
'message' => [
'type' => 'string',
'default' => 'Ciao da PHP!'
]
],
'render_callback' => function($attributes, $content, $block) {
$wrapper_attributes = get_block_wrapper_attributes();
return sprintf(
'<div %1$s>%2$s</div>',
$wrapper_attributes,
esc_html($attributes['message'] ?? 'Ciao!')
);
},
]);
Nessun build step, nessun npm, nessun node_modules. Il blocco appare nell’editor tramite ServerSideRender. Per i casi d’uso più semplici, è un’opzione solida.
Bonus: autoRegister (WordPress 7.0)
WordPress 7.0 introduce il flag autoRegister. Quando lo si imposta su true nei supports, il blocco PHP appare automaticamente nell’editor. E WordPress genera i controlli Inspector dalle definizioni degli attributi:
string→ campo testoboolean→ toggleinteger→ campo numericoenum→ dropdown
register_block_type( 'my-plugin/example', [
'title' => 'My Block',
'attributes' => [
'title' => [
'type' => 'string',
'default' => 'Hello World',
],
'count' => [
'type' => 'integer',
'default' => 5,
],
'enabled' => [
'type' => 'boolean',
'default' => true,
],
'size' => [
'type' => 'string',
'enum' => ['small', 'medium', 'large'],
'default' => 'medium',
],
],
'render_callback' => function ( $attributes ) {
return sprintf(
'<div>%s: %d items (%s)</div>',
esc_html( $attributes['title'] ),
$attributes['count'],
$attributes['size']
);
},
'supports' => [ 'autoRegister' => true ],
] );
Zero JavaScript. Nessuna riga. Sviluppatori PHP, bentornati.
Bonus: registrazione in blocco (WordPress 6.8+)
Per plugin con più blocchi, da WordPress 6.8 non serve più registrare ogni blocco singolarmente. Si genera un file manifest con wp-scripts e si registrano tutti i blocchi con una sola chiamata:
wp_register_block_types_from_metadata_collection(
__DIR__ . '/build',
__DIR__ . '/build/blocks-manifest.php'
);
Per generare il manifest, basta modificare gli script nel package.json:
{
"scripts": {
"build": "wp-scripts build --blocks-manifest",
"start": "wp-scripts start --blocks-manifest"
}
}
Si aggiunge una nuova cartella blocco, si lancia il build, e il blocco viene riconosciuto automaticamente.
Checklist: il tuo primo blocco in 5 minuti
npx @wordpress/create-block@latest my-block --variant=dynamiccd my-block && npm start- Modificare
src/edit.jsper personalizzare l’UI dell’editor - Modificare
src/render.phpper aggiungere l’output server-side - Modificare
block.jsonper impostare nome, attributi e supports npm run buildper la produzione- Comprimere la cartella del plugin e installare in WordPress
Scaffold. Customize. Build. Repeat.
Risorse
- Block Editor Handbook
- Block API Reference
- Block Attributes
- Gutenberg Repository
- Block Development Examples
