|
| 1 | +# Using Yii with Rapira |
| 2 | + |
| 3 | +[Rapira](https://rapira.rs/) is a PHP application server written in Rust that embeds the PHP interpreter. |
| 4 | +The [Yii Rapira runner](https://github.com/yiisoft/yii-runner-rapira) supports its classic, worker, and dispatcher modes. |
| 5 | +Worker and dispatcher modes initialize the application once per worker and reuse it for subsequent requests. |
| 6 | +See [Using Yii with event loop](using-with-event-loop.md) for the implications of keeping the application in memory. |
| 7 | + |
| 8 | +## Installation |
| 9 | + |
| 10 | +The runner requires PHP 8.4–8.5. Install the Rapira binary following the |
| 11 | +[Rapira installation instructions](https://rapira.rs/docs/intro/installation), using a PHP version supported by the runner. |
| 12 | +The Composer packages provide the Yii integration; the server binary must be installed separately. |
| 13 | + |
| 14 | +Install the runner and its contract package in your Yii application: |
| 15 | + |
| 16 | +```shell |
| 17 | +composer require yiisoft/yii-runner-rapira:@dev rapira/contract:@dev |
| 18 | +``` |
| 19 | + |
| 20 | +These stability flags allow the development versions used by the runner's installation instructions. |
| 21 | + |
| 22 | +## Configuration |
| 23 | + |
| 24 | +The following example assumes an application based on `yiisoft/app` or `yiisoft/app-api`, with `App\Environment` |
| 25 | +and `src/bootstrap.php` provided by the template. |
| 26 | + |
| 27 | +### Worker entry script |
| 28 | + |
| 29 | +Create `worker.php` in the application root: |
| 30 | + |
| 31 | +```php |
| 32 | +<?php |
| 33 | + |
| 34 | +declare(strict_types=1); |
| 35 | + |
| 36 | +use App\Environment; |
| 37 | +use Psr\Log\LogLevel; |
| 38 | +use Yiisoft\ErrorHandler\ErrorHandler; |
| 39 | +use Yiisoft\ErrorHandler\Renderer\PlainTextRenderer; |
| 40 | +use Yiisoft\Log\Logger; |
| 41 | +use Yiisoft\Log\StreamTarget; |
| 42 | +use Yiisoft\Yii\Runner\Rapira\RapiraApplicationRunner; |
| 43 | + |
| 44 | +$root = __DIR__; |
| 45 | + |
| 46 | +require_once $root . '/src/bootstrap.php'; |
| 47 | + |
| 48 | +$runner = new RapiraApplicationRunner( |
| 49 | + rootPath: $root, |
| 50 | + debug: Environment::appDebug(), |
| 51 | + checkEvents: Environment::appDebug(), |
| 52 | + environment: Environment::appEnv(), |
| 53 | + temporaryErrorHandler: new ErrorHandler( |
| 54 | + new Logger( |
| 55 | + [ |
| 56 | + (new StreamTarget())->setLevels([ |
| 57 | + LogLevel::EMERGENCY, |
| 58 | + LogLevel::ERROR, |
| 59 | + LogLevel::WARNING, |
| 60 | + ]), |
| 61 | + ], |
| 62 | + ), |
| 63 | + new PlainTextRenderer(), |
| 64 | + ), |
| 65 | +); |
| 66 | +$runner->run(); |
| 67 | +``` |
| 68 | + |
| 69 | +The runner creates the container, starts the application, converts incoming requests to PSR-7 requests, and emits |
| 70 | +responses. It detects the Rapira execution mode, so the same entry script can be used with all three modes. |
| 71 | + |
| 72 | +### Server configuration |
| 73 | + |
| 74 | +Create `rapira.toml` next to `worker.php`: |
| 75 | + |
| 76 | +```toml |
| 77 | +[http] |
| 78 | +listen = "127.0.0.1:8000" |
| 79 | + |
| 80 | +[pool] |
| 81 | +entrypoint = "worker.php" |
| 82 | +mode = "worker" |
| 83 | +max_requests = 1000 |
| 84 | +``` |
| 85 | + |
| 86 | +This configuration listens on the loopback interface and recycles each worker after 1,000 requests. |
| 87 | +For serving files from `public`, follow Rapira's [static file configuration](https://rapira.rs/docs/static-files). |
| 88 | +See the [configuration reference](https://rapira.rs/docs/configuration) for the other server and pool settings. |
| 89 | + |
| 90 | +## Starting a server |
| 91 | + |
| 92 | +Run the following command from the application root: |
| 93 | + |
| 94 | +```shell |
| 95 | +rapira serve |
| 96 | +``` |
| 97 | + |
| 98 | +Open `http://127.0.0.1:8000` to access the application. Restart the server after changing application code or configuration. |
| 99 | + |
| 100 | +## Execution modes |
| 101 | + |
| 102 | +Set `mode` in the `[pool]` section of `rapira.toml` to choose how requests are processed: |
| 103 | + |
| 104 | +- `classic` initializes the application for each request, similarly to PHP-FPM. |
| 105 | +- `worker` keeps the application in memory and receives requests through PHP's SAPI superglobals. |
| 106 | +- `dispatcher` keeps the application in memory and receives request objects through Rapira's dispatcher API. |
| 107 | + The Yii runner processes these requests sequentially within each worker. |
| 108 | + |
| 109 | +See [Rapira execution modes](https://rapira.rs/docs/execution-modes) for details. |
| 110 | + |
| 111 | +## On worker scope |
| 112 | + |
| 113 | +In worker and dispatcher modes, services may retain state between requests. The runner calls |
| 114 | +`Yiisoft\Di\StateResetter::reset()` after each request, but you must configure resetters for your own stateful services. |
| 115 | +See the [Yii DI documentation](https://github.com/yiisoft/di#resetting-services-state). |
| 116 | + |
| 117 | +The `max_requests` setting limits how long a worker lives; it does not replace resetting request-specific state. |
| 118 | + |
| 119 | +## Additional configuration |
| 120 | + |
| 121 | +`RapiraApplicationRunner` uses the application templates' web configuration groups by default. Its constructor accepts |
| 122 | +alternative groups, configuration directories, and a temporary error handler. Use `withConfig()` to supply a custom |
| 123 | +configuration instance or `withContainer()` to supply a PSR-11 container. See the |
| 124 | +[runner documentation](https://github.com/yiisoft/yii-runner-rapira#configuration) for examples. |
0 commit comments