Usando o Yii com FrankenPHP
O FrankenPHP é um servidor de aplicação PHP com o Caddy embutido. Ele pode rodar o Yii em modo worker, o que faz o bootstrap do framework acontecer uma vez por worker em vez de uma vez por requisição.
Instalação
O runner para FrankenPHP exige PHP 8.1–8.5. Instale o FrankenPHP seguindo as instruções de instalação dele, ou use a configuração Docker dos templates de aplicação do Yii, descrita abaixo.
Instale o pacote do runner com o Composer:
composer require yiisoft/yii-runner-frankenphpO FrankenPHP funciona especialmente bem em deploys com containers e é o runtime usado pela configuração Docker dos templates de aplicação do Yii, descrita em Docker nos templates de aplicação.
NOTE
Este runner é para o modo worker. Para usar o FrankenPHP no modo clássico, mantenha o public/index.php e o yiisoft/yii-runner-http, o runner HTTP padrão dos templates.
Configuração
Primeiro, configure o script de entrada do worker.
Script de entrada do worker
Crie /worker.php na raiz do projeto:
<?php
declare(strict_types=1);
use App\Environment;
use Psr\Log\LogLevel;
use Yiisoft\ErrorHandler\ErrorHandler;
use Yiisoft\ErrorHandler\Renderer\PlainTextRenderer;
use Yiisoft\Log\Logger;
use Yiisoft\Log\StreamTarget;
use Yiisoft\Yii\Runner\FrankenPHP\FrankenPHPApplicationRunner;
$root = __DIR__;
require_once $root . '/src/bootstrap.php';
if (Environment::appC3()) {
$c3 = $root . '/c3.php';
if (file_exists($c3)) {
require_once $c3;
}
}
$runner = new FrankenPHPApplicationRunner(
rootPath: $root,
debug: Environment::appDebug(),
checkEvents: Environment::appDebug(),
environment: Environment::appEnv(),
temporaryErrorHandler: new ErrorHandler(
new Logger(
[
(new StreamTarget())->setLevels([
LogLevel::EMERGENCY,
LogLevel::ERROR,
LogLevel::WARNING,
]),
],
),
new PlainTextRenderer(),
),
);
$runner->run();O runner faz o bootstrap da aplicação uma vez e depois continua processando requisições em modo worker. Diferente do public/index.php clássico, este script não é executado a cada requisição.
Configuração do servidor
O FrankenPHP é configurado por um Caddyfile. Em produção, ele pode ficar assim:
{
skip_install_trust
frankenphp {
}
}
{$SERVER_NAME::80} {
encode zstd br gzip
php_server {
root /app/public
worker {
match *
file /app/worker.php
}
}
}Essa configuração diz ao FrankenPHP para servir o diretório public e atender todas as requisições com o worker.php. Os assets estáticos continuam sendo servidos de public, enquanto as requisições PHP são processadas pelo worker de longa duração.
Em desenvolvimento, adicione watch para que o FrankenPHP recarregue os workers quando arquivos PHP mudarem:
{
skip_install_trust
frankenphp {
}
}
{$SERVER_NAME::80} {
encode zstd br gzip
php_server {
root /app/public
worker {
match *
file /app/worker.php
watch /app/**/*.php
}
}
}Configuração Docker nos templates de aplicação do Yii
Os templates de aplicação do Yii já vêm com uma configuração Docker baseada no FrankenPHP. Para passar a aplicação para o modo worker, altere os arquivos da estrutura Docker em vez de depender do public/index.php.
Crie /worker.php na raiz do projeto como mostrado acima e depois altere a configuração do Caddy usada pelo container. Em desenvolvimento, edite docker/dev/Caddyfile:
{
skip_install_trust
frankenphp {
}
}
{$SERVER_NAME::80} {
encode zstd br gzip
php_server {
root /app/public
worker {
match *
file /app/worker.php
watch /app/**/*.php
}
}
}Em produção, use a mesma configuração sem watch em docker/Caddyfile:
{
skip_install_trust
frankenphp {
}
}
{$SERVER_NAME::80} {
encode zstd br gzip
php_server {
root /app/public
worker {
match *
file /app/worker.php
}
}
}Os templates usam dunglas/frankenphp como imagem base em docker/Dockerfile, montam o projeto em /app no desenvolvimento e passam a configuração de runtime por arquivos de ambiente como docker/dev/.env e docker/prod/.env. O valor padrão de SERVER_NAME nesses arquivos é :80, que corresponde aos exemplos acima.
Depois de alterar o worker.php e o Caddyfile correspondente, reconstrua a imagem e reinicie o ambiente:
make build
make upEm produção, reconstrua a imagem de produção e faça o deploy usando o fluxo Docker de produção do projeto.
Se você passar totalmente para o modo worker, o public/index.php e o yiisoft/yii-runner-http deixam de ser necessários.
Iniciando o servidor
O comando exato para iniciar depende de como você roda o FrankenPHP:
- Nos templates de aplicação do Yii, execute
make buildemake updepois de alterar oworker.phpe oCaddyfilecorrespondente. - Com o binário standalone, execute o seguinte comando no diretório que contém o seu
Caddyfile:
frankenphp run --config CaddyfileA configuração de exemplo usa /app como raiz da aplicação. Ajuste /app/public, /app/worker.php e o caminho do watch conforme a sua instalação. Veja a referência de configuração do FrankenPHP para outras opções de deploy.
Sobre o escopo do worker
- A memória de cada worker é isolada da dos outros workers.
- Um único worker atende várias requisições, então os serviços criados dentro dele podem manter estado entre requisições.
- A cada iteração do event loop, todo serviço com estado deve ser redefinido.
Para as implicações gerais de workers de longa duração, veja Usando o Yii com event loop.
Notas sobre o modo worker
- Use a variável de ambiente
MAX_REQUESTSpara limitar quantas requisições um worker atende antes de ser reiniciado. - O runner chama
Yiisoft\Di\StateResetter::reset()depois de cada requisição. Registre resetters para os seus serviços com estado, como descrito na documentação do Yii DI.
Configuração adicional
O FrankenPHPApplicationRunner vem configurado por padrão para os templates de aplicação do Yii e segue o conceito de configuração do container de dependências.
O construtor permite sobrescrever a configuração padrão de bootstrap, eventos, DI, params e tratamento de erros. Você também pode fornecer uma instância de configuração personalizada com withConfig() e um container personalizado com withContainer().