# FrankenPHP

> Supercharge your Yii2 applications with FrankenPHP blazing-fast HTTP server

**Supercharge your Yii2 applications with FrankenPHP blazing-fast HTTP server**

_HTTP/2, HTTP/3, automatic memory management, and worker mode for ultimate performance_

## Features

![Feature Overview](/docs/_astro/features.3QuEs2Gw.svg)

## Demo

Explore the ready-to-run Yii2 + FrankenPHP application template.

### Installation

```bash
composer require yii2-extensions/franken-php:^0.4 httpsoft/http-message
```

### Quick start

Create `web/index.php` in an existing Yii application with its routes and secret `request.cookieValidationKey`
already configured.

```php
<?php

declare(strict_types=1);

use HttpSoft\Message\{ResponseFactory, ServerRequestFactory, StreamFactory, UploadedFileFactory};
use Psr\Http\Message\{
    ResponseFactoryInterface,
    ServerRequestFactoryInterface,
    StreamFactoryInterface,
    UploadedFileFactoryInterface,
};
use yii2\extensions\frankenphp\FrankenPHP;
use yii2\extensions\psrbridge\http\Application;

ini_set('session.use_cookies', '0');

define('YII_DEBUG', filter_var(getenv('YII_DEBUG'), FILTER_VALIDATE_BOOLEAN));
define('YII_ENV', getenv('YII_ENV') ?: 'prod');

require dirname(__DIR__) . '/vendor/autoload.php';
require dirname(__DIR__) . '/vendor/yiisoft/yii2/Yii.php';

$config = require dirname(__DIR__) . '/config/web.php';

$config['container']['definitions'][ResponseFactoryInterface::class] = ResponseFactory::class;
$config['container']['definitions'][ServerRequestFactoryInterface::class] = ServerRequestFactory::class;
$config['container']['definitions'][StreamFactoryInterface::class] = StreamFactory::class;
$config['container']['definitions'][UploadedFileFactoryInterface::class] = UploadedFileFactory::class;

$runner = new FrankenPHP(new Application($config));
$runner->run();
```

The runner emits each PSR response and then completes the bridge's `finalize()` lifecycle exactly once. HEAD omits
the response body. Keep request-scoped components out of `persistentComponents`; lazy sessions remain isolated
when `useSession=false`. See [configuration](/docs/extensions/franken-php/configuration/index.md) and [worker examples](/docs/extensions/franken-php/examples/index.md).

### FrankenPHP configuration

Create `Caddyfile` in your project root (worker mode)

```caddyfile
{
    auto_https off
    admin localhost:2019
    https_port 8443

    frankenphp {
        worker ./web/index.php
    }
}

localhost {
    tls ./web/ssl/localhost.pem ./web/ssl/localhost-key.pem

    log

    encode zstd br gzip

    root ./web

    # request hints for frameworks that consume X-Sendfile-Type and X-Accel-Mapping
    # see: https://github.com/php/frankenphp/blob/main/docs/x-sendfile.md
    request_header X-Sendfile-Type x-accel-redirect
    request_header X-Accel-Mapping ../private-files=/private-files

    intercept {
        @sendfile header X-Accel-Redirect *
        handle_response @sendfile {
            root private-files/
            rewrite * {resp.header.X-Accel-Redirect}
            method * GET
            header -X-Accel-Redirect
            file_server
        }
    }

    php_server {
        try_files {path} index.php
    }
}
```

:::caution
**Note:** Using custom certificates (like `tls ./web/ssl/localhost.pem ./web/ssl/localhost-key.pem`) avoids browser trust warnings that occur with Caddy's automatic self-signed certificates.
For local development, consider using [mkcert](https://github.com/FiloSottile/mkcert) to generate trusted local certificates.
If you want to use Caddy's automatic self-signed certificates for local development, you can remove this line.
:::

For Yii, select the response header explicitly. The URI is relative to the interceptor's `private-files/` root:

```php
return Yii::$app->response->xSendFile('/report.pdf', 'report.pdf', ['xHeader' => 'X-Accel-Redirect']);
```

This serves `private-files/report.pdf`. Authorize access and select the file on the server before returning the
response. Yii's default `X-Sendfile` response header is not matched by this interceptor.

### Standalone Binary

Install a worker-capable binary following the [official FrankenPHP instructions](https://frankenphp.dev/docs/),
then run from the application root:

```bash
frankenphp run --config Caddyfile --watch
```

On Windows, use [WSL](https://learn.microsoft.com/windows/wsl/).

### Docker

Alternatively, [Docker images](https://frankenphp.dev/docs/docker/) are available.

#### Worker mode

Gitbash/Windows

```bash
docker run \
  -e CADDY_GLOBAL_OPTIONS="auto_https off" \
  -e CADDY_SERVER_EXTRA_DIRECTIVES="tls /app/web/ssl/localhost.pem /app/web/ssl/localhost-key.pem" \
  -e FRANKENPHP_CONFIG="worker ./web/index.php" \
  -e SERVER_NAME="https://localhost:8443" \
  -e SERVER_ROOT="./web" \
  -v "//k/yii2-extensions/app-basic:/app" \
  -p 8443:8443 \
  -p 8443:8443/udp \
  --name yii2-frankenphp-worker \
  dunglas/frankenphp
```

> **Note:** Paths in the example (`//k/yii2-extensions/app-basic`) are for demonstration purposes only.
> Replace them with the actual path to your Yii2 project on your system.

Linux/WSL

```bash
docker run \
  -e CADDY_GLOBAL_OPTIONS="auto_https off" \
  -e CADDY_SERVER_EXTRA_DIRECTIVES="tls /app/web/ssl/localhost.pem /app/web/ssl/localhost-key.pem" \
  -e FRANKENPHP_CONFIG="worker ./web/index.php" \
  -e SERVER_NAME="https://localhost:8443" \
  -e SERVER_ROOT="./web" \
  -v $PWD:/app \
  -p 8443:8443 \
  -p 8443:8443/udp \
  --name yii2-frankenphp-worker \
  dunglas/frankenphp
```

:::caution[Important]
Your application will be available at `https://localhost:8443` or at the address set in the `Caddyfile`.
:::

### Development & Debugging

For enhanced debugging capabilities and proper time display in FrankenPHP, install the worker debug extension.

```bash
composer require --dev yii2-extensions/worker-debug:^0.1
```

Add the following to your development configuration (`config/web.php`):

```php
<?php

declare(strict_types=1);

use yii2\extensions\debug\WorkerDebugModule;

if (YII_ENV_DEV) {
    // configuration adjustments for 'dev' environment
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = [
        'class' => WorkerDebugModule::class,
        // uncomment the following to add your IP if you are not connecting from localhost.
        //'allowedIPs' => ['127.0.0.1', '::1'],
    ];
}
```

### File Upload Handling

Use `yii2\extensions\psrbridge\http\UploadedFile` in the application's upload model. Validate file content and size,
use a server-generated storage name, and check `saveAs()` before reporting success. See
[uploads and streaming downloads](/docs/extensions/franken-php/examples/index.md#uploads-and-streaming-downloads).

## Documentation

Practical guides and complete worker examples for FrankenPHP and request
isolation.

- 📚 [Installation Guide](/docs/extensions/franken-php/installation/index.md)
- ⚙️ [Configuration Guide](/docs/extensions/franken-php/configuration/index.md)
- 💡 [Worker Examples](/docs/extensions/franken-php/examples/index.md)
- 🔄 [Upgrade Guide](https://github.com/yii2-extensions/franken-php/blob/main/UPGRADE.md) and [Migration Checks](/docs/extensions/franken-php/migration/index.md)
- 🧪 [Testing Guide](/docs/extensions/franken-php/testing/index.md)

## AI assistance

AI agents: use the repository guides and source for the installed revision.
For a [documentation deployment](https://yii2-framework.github.io/docs/) with
`llms.txt`, read that index first. When Markdown export is enabled, append
`index.md` to a page URL. For Yii conventions, use the `yii2-framework` skill
from a local framework documentation checkout.

- 🤖 [yii2-frankenphp-worker skill](/docs/extensions/franken-php/agents/index.md): factories and isolation.

If the hosted sources are unavailable, use the repository guides and locally
available skills.

## Our social networks

[Follow on X](https://x.com/Terabytesoftw)

## License

[License](https://github.com/yii2-extensions/franken-php/blob/main/LICENSE)

## Package

- Source code and issues: [yii2-extensions/franken-php](https://github.com/yii2-extensions/franken-php). Star the repository if the package is useful to you.
- Composer package: [yii2-extensions/franken-php](https://packagist.org/packages/yii2-extensions/franken-php).
- Changelog: [CHANGELOG.md](https://github.com/yii2-extensions/franken-php/blob/main/CHANGELOG.md).