PHP & WordPress
bext prend en charge les applications PHP dans deux modes :
- Proxy FastCGI — Transférer les requêtes vers les pools PHP-FPM existants ( WordPress, Laravel, Symfony, toute application PHP)
- Runtime PHP intégré — Exécutez PHP directement dans bext avec le micro-framework (zéro dépendance externe)
WordPress et PHP-FPM (mode compatible nginx)#
Lors de la migration depuis nginx, bext détecte automatiquement les sites WordPress et achemine les requêtes PHP via FastCGI vers vos sockets PHP-FPM existants. Aucune configuration nécessaire.
Comment ça marche#
- bext analyse votre configuration nginx et trouve les directives
fastcgi_pass - Les sites WordPress sont détectés automatiquement en recherchant
wp-config.php/wp-content - Les requêtes PHP (fichiers
.php, solutions de replitry_files) sont transmises à PHP-FPM via le protocole FastCGI - Les ressources statiques (CSS, JS, images) sont servies directement à partir du disque – jamais acheminées via PHP
- Les connexions à PHP-FPM sont regroupées pour des raisons de performances (8 connexions inactives par socket)
Fonctionnalités prises en charge#
- Administrateur WordPress (
/wp-admin/), connexion (/wp-login.php), cron (/wp-cron.php) - Jolis permaliens via
try_files $uri /index.php - Variables
$_SERVERentièrement renseignées (REQUEST_URI,HTTP_HOST,SCRIPT_FILENAME, etc.) - HTTP/2 avec mappage
:authority→HTTP_HOSTcorrect - Plusieurs versions de PHP par serveur (PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4)
- Pools PHP-FPM par site avec sockets Unix isolés
- Suivi de l'expiration des certificats SSL pour tous les domaines
Gestion du cloud#
Après la migration, synchronisez vos sites avec le tableau de bord bext cloud :
bext login # authenticate with bext cloud
bext nginx sync-cloud # sync all sites + metadata
Le tableau de bord cloud affiche chaque site WordPress avec :
- Version PHP et chemin du socket FPM
- Dates d'expiration du certificat SSL
- Nombre de domaines et statut de vérification
- Propriété de l'agence/du client
Détection du framework#
| Cadre | Détection | Action |
|---|---|---|
| WordPress | wp-config.php ou wp-content/ à la racine du document |
FastCGI → PHP-FPM |
| Laravel | Fichier artisan dans le répertoire parent |
FastCGI → PHP-FPM |
| Symfony | bin/console dans le répertoire parent |
FastCGI → PHP-FPM |
| PHP générique | Toute directive fastcgi_pass |
FastCGI → PHP-FPM |
Micro-framework PHP intégré#
Le package bext/framework est un micro-framework PHP léger (~ 200 lignes) avec routage basé sur des fichiers, conçu pour s'exécuter dans le runtime PHP intégré de bext.
Installation#
composer require bext/framework
Configuration requise pour : PHP >= 8.2
Structure du projet#
my-php-app/
├── worker.php # Entry point
├── app/
│ ├── pages/ # File-based HTML routes (ISR cached)
│ │ ├── index.php # GET /
│ │ ├── about.php # GET /about
│ │ └── products/
│ │ ├── index.php # GET /products
│ │ └── [id].php # GET /products/:id
│ ├── api/ # File-based API routes (JSON, never cached)
│ │ ├── health.php # GET /api/health
│ │ └── products/
│ │ └── [id].php # GET/POST/PUT/DELETE /api/products/:id
│ └── layouts/
│ └── default.php # Wraps all page routes
├── public/ # Static assets (CSS, JS, images)
└── bext.config.toml
Point d'entrée#
<?php
// worker.php
require __DIR__ . '/vendor/bext/bext.php';
Bext\App::run(__DIR__ . '/app');
Configuration#
# bext.config.toml
[php]
enabled = true
document_root = "./public"
workers = 4
worker_script = "./worker.php"
extensions = [".php"]
index = "index.php"
Itinéraires de pages#
Les fichiers dans app/pages/ servent des réponses HTML. Les requêtes GET sont mises en cache ISR par bext.
Fermeture simple#
<?php
// app/pages/index.php
return function (array $params, array $query) {
return "<h1>Welcome</h1><p>Hello from bext!</p>";
};
Objet avec métadonnées#
Renvoyez un objet avec render() pour la prise en charge des balises de cache :
<?php
// app/pages/products/[id].php
return new class {
public string $title = 'Product Detail';
public string $cache_tag = 'products:detail';
public function render(array $params, array $query): string
{
$id = $params['id'];
$product = db_get_product($id);
return <<<HTML
<h1>{$product['name']}</h1>
<p>{$product['description']}</p>
<p class="price">\${$product['price']}</p>
HTML;
}
};
La propriété $cache_tag indique au cache ISR de bext à quelle balise appartient cette page, permettant une invalidation ciblée avec Bext\App::invalidate("products:detail").
HTML statique#
Pour les pages simples, renvoyez simplement une chaîne :
<?php
// app/pages/about.php
return '<h1>About Us</h1><p>We build fast things.</p>';
Segments dynamiques#
Utilisez [param] dans les noms de fichiers pour les segments d'itinéraire dynamiques :
app/pages/products/[id].php → /products/:id
app/pages/blog/[slug].php → /blog/:slug
app/api/users/[userId]/posts.php → /api/users/:userId/posts
Les valeurs des paramètres sont transmises dans le tableau $params :
return function (array $params, array $query) {
$id = $params['id']; // from URL segment
$page = $query['page']; // from ?page=2
// ...
};
Itinéraires API#
Les fichiers dans app/api/ servent les réponses JSON. Ils ne sont jamais mis en cache ISR et prennent en charge la répartition de la méthode HTTP.
Objet avec gestionnaires de méthodes#
<?php
// app/api/products/[id].php
return new class {
public function GET(array $params, array $query): array
{
return db_get_product($params['id']);
}
public function POST(array $params, array $body): array
{
$product = db_create_product($body);
return ['created' => true, 'id' => $product['id'], 'status' => 201];
}
public function PUT(array $params, array $body): array
{
db_update_product($params['id'], $body);
return ['updated' => true];
}
public function DELETE(array $params): array
{
db_delete_product($params['id']);
return ['deleted' => true];
}
};
La clé status dans le tableau de retour définit le code d'état HTTP (par défaut : 200).
Clôture avec expédition de méthode#
<?php
return function (string $method, array $params, array $query, ?array $body) {
return match ($method) {
'GET' => ['items' => get_all_items()],
'POST' => ['created' => create_item($body)],
default => ['error' => 'Method not allowed', 'status' => 405],
};
};
Mises en page#
Les fichiers dans la sortie de routage de page app/layouts/ :
<?php
// app/layouts/default.php
return function (string $html, array $meta): string {
$title = $meta['title'] ?? 'My App';
return <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{$title}</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<nav>
<a href="/">Home</a>
<a href="/products">Products</a>
<a href="/about">About</a>
</nav>
<main>{$html}</main>
<footer>© 2026 My App</footer>
</body>
</html>
HTML;
};
Le tableau $meta contient les propriétés de l'objet itinéraire de page ( $title, $cache_tag, etc.).
Services de plateforme#
Méthodes statiques pour les services bext :
// Invalidate ISR cache
Bext\App::invalidate("products");
// Publish real-time event
Bext\App::publish("orders", ["id" => 123, "status" => "shipped"]);
// Register a scheduled task
Bext\App::schedule("cleanup", "0 2 * * *", "cache::gc");
Comment fonctionne le routage#
- La demande arrive → bext correspond à l'itinéraire vers un fichier dans
app/pages/ouapp/api/ - Les segments
[param]sont extraits de l'URL - Le fichier est
required et sa valeur de retour est évaluée :
- Fermeture → appelé avec
($params, $query)pour les pages,($method, $params, $query, $body)pour l'API - Objet avec
render()→render($params, $query)appelé, métadonnées extraites - Objet avec méthode HTTP → la méthode de correspondance est appelée
- Chaîne → renvoyé directement
- Pour les pages : la sortie est enveloppée dans la mise en page, mise en cache ISR avec toutes les balises spécifiées
- Pour les routes API : la sortie est codée en JSON, jamais mise en cache
Cette page couvre le micro-framework PHP intégré et le mode proxy FastCGI. Pour héberger une installation complète de WordPress avec purge lors du changement, la barre d'administration et la prise en charge multisite, voir Intégration WordPress.
Les fichiers dans app/api/ sont des jamais mis en cache ISR — seules les réponses app/pages/ sont mises en cache. Si vous devez mettre en cache une réponse API, déplacez-la dans app/pages/ et renvoyez plutôt une chaîne JSON.
En rapport#
- Intégration WordPress — WordPress complet + WooCommerce derrière le cache périphérique de bext
- Mode mascarade — comment bext analyse les configurations nginx pour piloter la répartition FastCGI
- Mise en cache — TTL ISR, obsolète pendant la revalidation et invalidation des balises de cache
- Adaptateur Laravel — Fournisseur de services PHP pour les services SDK bext
- Adaptateur Symfony — Offre groupée Symfony avec services bext autocâblés
Links#
- php.net — Référence du langage PHP