Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Yii Runner Laravel Package

yiisoft/yii-runner

Base runner infrastructure for Yii applications, providing a common interface and helpers for bootstrapping the dependency injection container and executing an app. Pair it with HTTP or console runner packages to create clean, environment-specific entry scripts.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package. yiisoft/yii-runner is the abstract bootstrap layer for Yii3 applications: it loads layered config, builds a PSR-11 container via yiisoft/config, wires an error handler, and hands control to either an HTTP kernel (yiisoft/yii-http), a console kernel (yiisoft/yii-console), or a long-running worker (RoadRunner/Swoole). There is no service provider, no facade, no config/runner.php to publish. As a Laravel developer you adopt it in one of two situations: you are working inside a Yii3 codebase, or you want a second, framework-agnostic process (queue consumer, cron, webhook endpoint) bootstrapping from the same Composer tree as a Laravel app.

Look first at these files, in order:

  1. src/Runner.php — the abstract run() contract; everything else is a variation on it.
  2. src/ConfigTrait.php — the config layering, rootPath, debug, environment, merge-plan logic. This is the actual value of the package.
  3. src/ErrorHandler.php — register() / restore(), error-to-exception conversion.
  4. src/RunnerHelper.php — how YII_ENV / YII_DEBUG are resolved from the environment.

Then read the concrete siblings, because the base package alone is inert: yiisoft/yii-runner-http, yiisoft/yii-runner-console, and yiisoft/yii-runner-roadrunner. The yiisoft/app template is the canonical wiring example.

Minimal adoption (equivalent of public/index.php + bootstrap/app.php):

// public/index.php
declare(strict_types=1);

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

$runner = new \Yiisoft\Yii\Runner\Http\HttpRunner(
    rootPath: dirname(__DIR__),
    debug: (bool) ($_ENV['YII_DEBUG'] ?? false),
    environment: $_ENV['YII_ENV'] ?? 'prod',
);

$runner->run();

Layout it expects: config/ (app config), config/packages/ (per-vendor-package config fragments), config/params.php, optional config/environments/{env}/, and a generated config/.merge-plan.php.

First real use case: a Laravel app that needs a standalone CLI worker for a domain library. You keep Laravel for the web tier, but run the worker through a small Yii runner so the library gets a DI container and config without dragging in Illuminate\Foundation. If you only want the container and not the request lifecycle, skip the runner entirely and use yiisoft/config's ConfigLoader + yiisoft/di directly.

Implementation Patterns

Config layering instead of a single config/app.php. The runner merges config from the app, from each installed package's config/ fragment, and from the environment directory. In Laravel terms this is mergeConfigFrom() for every package, automatically, plus config:cache semantics baked into the boot. The merge plan file records which fragments were discovered; when you composer require a Yii package, the plan changes and the config graph grows without you editing the app config.

Parameter indirection. config/params.php values are referenced as ${param} in service definitions and can come from env. Use this for the same things you'd use env() for, but resolve them at container-build time so the compiled definitions are static — important under RoadRunner/Swoole, where the container is built once and reused across requests.

Same config, multiple entry points. This is the biggest architectural win and the closest analogue to Laravel's Kernel split. bin/console, public/index.php, and a RoadRunner worker all construct a different runner subclass over the same config/ directory. Adding a queue consumer or a health-check endpoint is a new 10-line entry file, not a new bootstrap.

Custom runner for bespoke lifecycles. For a cron job or a worker that owns its own loop:

final class WorkerRunner extends \Yiisoft\Yii\Runner\Runner
{
    use \Yiisoft\Yii\Runner\ConfigTrait;

    public function run(): void
    {
        $container = $this->loadConfig();
        $container->get(\App\Worker::class)->run();
        // loop, signal handling, graceful shutdown
    }
}

ConfigTrait::loadConfig() is the extension point; everything the stock runners do is downstream of it. That trait is also the honest answer to "can I reuse this from Laravel?" — you can call it from an Artisan command to get a PSR-11 container, but do not call run() there, since run() owns the process and emits the response/terminates.

Cross-framework sharing. Anything you build on this should be PSR-7/PSR-11 only, never Illuminate\Http\Request. Then both sides can consume it: Laravel wraps it, Yii feeds it natively. In practice, share the domain service and the config contract; let each framework keep its own HTTP layer.

Environment matrix. Treat YII_ENV (prod, dev, test) and YII_DEBUG as the two switches. YII_DEBUG controls error verbosity, stack traces, and (in some runners) container definition checks; it should never be true outside local/test. Keep it out of .env.example defaults and set it explicitly in your deploy config.

Gotchas and Tips

  • The base package does nothing on its own. composer require yiisoft/yii-runner gives you abstractions. You need a concrete runner (-http, -console, -roadrunner) or your own subclass. Zero dependents on Packagist means zero copy-paste examples from the community — read the sibling packages' source, they are short.
  • YII_ENV, not APP_ENV. RunnerHelper reads YII_ENV / YII_DEBUG. If you're booting this inside a Laravel process expecting Laravel's env vars to carry over, they won't. Bridge them explicitly in whatever constructs the runner.
  • Do not register both error handlers. ErrorHandler::register() replaces the PHP error handler and installs a shutdown function. Calling it in a process that already has Laravel's handler registered produces confusing "handled twice" behavior and lost exception reports. In a hybrid process, use register() / restore() around the Yii-side call, or skip it entirely and let the host framework handle errors.
  • Stale merge plan. If you add or remove a package and the merge plan isn't regenerated, its config/ fragment is silently ignored. Symptom: a service definition "not found" that you can plainly see in the vendor directory. Regenerate the plan; if you deploy with a build artifact, rebuild it in CI, not on the server.
  • Long-running process state. Under RoadRunner/Swoole, config and container are built once. Config edits require a worker reload — the implicit equivalent of php artisan config:cache, but with no command to run. Same discipline as Octane: no mutable singletons, no request-scoped state in container-shared services.
  • Debug flag leakage. debug: true in a worker means stack traces in logs and, depending on the error handler, possibly in responses. Bind it to an env var that is set to false by the deploy config rather than computed from a hostname check.
  • Named-argument signatures drift. Runner constructors take named args (rootPath, debug, environment, configDirectory, vendorDirectory) and have gained parameters across releases. Pin the version and read the concrete runner's __construct rather than trusting a blog snippet.
  • PSR-7 is the seam. HTTP runners hand you PSR-7 in/out. Any Laravel integration must translate at the boundary; don't try to teach the runner about Illuminate\Http\Request.
  • Debugging config resolution: load the config manually in a tinker-style script ((new ConfigTrait impl)->loadConfig()) and var_dump the resulting definitions. Faster than reading merge plans by hand when a parameter resolves to the wrong value.
  • License is BSD-3-Clause — permissive, no copyleft concerns, but note it's a small, low-traffic project maintained by the Yii core team; budget for reading source over finding answers online.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle