yii3 / inertia
Inertia.js v3 server-side integration for Yii3.
Requires
- php: >=8.3
- php-forge/inertia: ^0.2
- php-forge/vite: ^0.2
- psr/http-factory: ^1.1
- psr/http-message: ^1.1 || ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- yiisoft/aliases: ^3.1
- yiisoft/cookies: ^1.2
- yiisoft/csrf: ^2.2
- yiisoft/json: ^1.1
- yiisoft/request-provider: ^1.3
- yiisoft/session: ^3.0
- yiisoft/view: ^12.2
Requires (Dev)
- httpsoft/http-message: ^1.1
- infection/infection: ^0.35
- maglnet/composer-require-checker: ^4.1
- php-forge/baseline: ^0.2
- php-forge/coding-standard: ^0.3
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0.3
- phpunit/phpunit: ^12.5
- yii2-extensions/scaffold: ^0.2
This package is auto-updated.
Last update: 2026-08-27 20:06:35 UTC
README
Inertia for Yii3
Connect Yii3 requests, responses, views, sessions, and redirects to the Inertia protocol
Server-side Inertia.js v3 integration for Yii3. The package uses constructor injection, PSR-7 responses, PSR-15 middleware, and Yii Config Plugin configuration. It does not expose a static facade or read from a service locator.
Architecture
The packages have deliberately separate responsibilities:
php-forge/inertiaimplements the framework-agnostic protocol, page model, prop resolution, headers, redirects, and result objects.yii3/inertiaadapts Yii3 request, response, session, and view services to that core.php-forge/viteprovides framework-agnostic Vite manifest and development server support for the initial document.
React and Vue remain application concerns; this adapter does not ship framework-specific JavaScript packages.
Requirements
- PHP 8.3 or later.
- A Yii3 application with PSR-17 response and stream factories.
yiisoft/sessionandyiisoft/csrffor flash data, validation errors, and the XSRF cookie flow.yiisoft/request-body-parserfor JSON form submissions.yiisoft/viewfor rendering the initial HTML document through the application web view.php-forge/inertiafor the framework-neutral Inertia protocol and prop types.php-forge/vitefor framework-neutral asset resolution.
Installation
Applications should declare the adapter, the native PHP Forge packages they use, and Yii's request body parser as direct dependencies:
composer require yii3/inertia:^0.1 php-forge/inertia:^0.2 php-forge/vite:^0.2 yiisoft/request-body-parser:^1.2
For a local sibling checkout, add a Composer path repository:
{
"repositories": [
{
"type": "path",
"url": "../inertia",
"options": {
"symlink": true,
"reference": "config"
}
}
],
"require": {
"yii3/inertia": "dev-main",
"php-forge/inertia": "^0.2",
"php-forge/vite": "^0.2",
"yiisoft/request-body-parser": "^1.2"
}
}
The Yii Config Plugin merges config/params.php and the web-only config/di-web.php automatically.
Middleware order
Place the middleware around the Yii3 web stack in this order:
use Yii3\Inertia\Middleware\CsrfTokenCookieMiddleware; use Yii3\Inertia\Middleware\InertiaMiddleware; use Yiisoft\Csrf\CsrfTokenMiddleware; use Yiisoft\ErrorHandler\Middleware\ErrorCatcher; use Yiisoft\Request\Body\RequestBodyParser; use Yiisoft\RequestProvider\RequestCatcherMiddleware; use Yiisoft\Router\Middleware\Router; use Yiisoft\Session\SessionMiddleware; return [ InertiaMiddleware::class, ErrorCatcher::class, SessionMiddleware::class, RequestBodyParser::class, CsrfTokenCookieMiddleware::class, CsrfTokenMiddleware::class, RequestCatcherMiddleware::class, Router::class, ];
This order ensures that:
- Inertia headers are added to normal and error responses.
- JSON form bodies are available before CSRF validation.
- The session is open when the readable
XSRF-TOKENcookie is generated. - Mutable shared props are reset before and after every request, including failed requests.
The package configures Yii's CSRF validator to accept X-XSRF-TOKEN. Do not encrypt or sign the XSRF-TOKEN
cookie with CookieMiddleware; the browser client must be able to read and return the masked token.
Configuration
Override the yii3/inertia parameter tree in application configuration:
<?php declare(strict_types=1); $manifest = dirname(__DIR__, 2) . '/public/build/.vite/manifest.json'; return [ 'yii3/inertia' => [ 'title' => 'My application', 'version' => static function () use ($manifest): string|null { if (!is_file($manifest)) { return null; } $hash = hash_file('xxh128', $manifest); return $hash === false ? null : $hash; }, 'shared' => [ 'application' => ['name' => 'My application'], ], 'csrf' => [ // null enables HTTPS auto-detection. Use true only when trusted-proxy // middleware does not normalize the request URI scheme. 'secure' => null, ], ], ];
The full parameter tree contains:
id,rootView,language,charset, andtitlefor the initial document.version,shared, anderrorFlashKeyfor page construction.csrf.cookieName,headerName,parameterName,path,domain,secure, andsameSite.
Configurable services keep constructors to at most four dependencies. Yii's DI definitions apply package parameters
through immutable with*() methods, so each configured instance is cloned instead of mutated.
The configured root-view alias is resolved with Yiisoft\Aliases\Aliases and rendered by the application's
Yiisoft\View\WebView. Custom root views therefore use Yii's configured renderers, themes, common parameters, and
render events instead of a package-owned PHP file loader.
Vite integration
The application owns its Vite mode and entrypoints. Define the native PHPForge\Vite\Vite service directly; the
package injects it into RootViewRenderer, which renders the resulting assets with the native stateless
HtmlRenderer.
Production example:
<?php declare(strict_types=1); use PHPForge\Vite\Configuration\ProductionConfiguration; use PHPForge\Vite\Vite; return [ Vite::class => static fn(): Vite => Vite::create( ProductionConfiguration::create( manifestPath: dirname(__DIR__, 2) . '/public/build/.vite/manifest.json', assetBaseUrl: '/build', ), entrypoints: ['resources/js/app.ts'], ), ];
During development, register the native development service:
<?php declare(strict_types=1); use PHPForge\Vite\Configuration\DevelopmentConfiguration; use PHPForge\Vite\Vite; return [ Vite::class => static fn(): Vite => Vite::create( DevelopmentConfiguration::create('http://localhost:5173'), entrypoints: ['resources/js/app.ts'], ), ];
React applications may pass an application-owned InlineModuleProviderInterface implementation to
DevelopmentConfiguration::create() for the React Refresh preamble. Vue applications do not need a preamble.
Rendering pages
Inject Yii3\Inertia\Inertia into an action and return its PSR-7 response. Use the native PHP Forge prop factories;
this package does not duplicate them.
use PHPForge\Inertia\Prop\Prop; use PHPForge\Inertia\Prop\ScrollMetadata; use Psr\Http\Message\ResponseInterface; use Yii3\Inertia\Inertia; final readonly class DashboardAction { public function __construct(private Inertia $inertia) {} public function __invoke(): ResponseInterface { $this->inertia->share('auth.user', ['id' => 42, 'name' => 'Ada']); return $this->inertia->render('Dashboard', [ 'summary' => static fn(): array => ['projects' => 12], 'activity' => Prop::defer(static fn(): array => loadActivity(), 'dashboard', rescue: true), 'audit' => Prop::optional(static fn(): array => loadAudit())->once(), 'permissions' => Prop::always(['projects.read']), 'users' => Prop::merge(loadUsers())->append('data', matchOn: 'id'), 'messages' => Prop::merge(loadMessages())->prepend(), 'settings' => Prop::merge(loadSettings())->deepMerge(), 'countries' => Prop::once(static fn(): array => loadCountries()) ->as('country-list') ->until(3600), 'feed' => Prop::scroll( loadFeed(), new ScrollMetadata('page', previousPage: null, nextPage: 2, currentPage: 1), ), ]); } }
Plain page, shared, and version closures are invoked without arguments, matching the PHP Forge core contract. Resolve request-dependent values explicitly in the action or capture the request in a zero-argument closure. Scroll metadata closures are the exception: the core passes them the resolved scroll value.
Page props replace shared props at the top-level key, matching the official adapter behavior. The response exposes the
top-level shared keys through sharedProps, allowing Inertia v3 instant visits to retain shared application data.
Session flash data is emitted only in the page-level flash field so it cannot replay from browser-history props.
Public API
Yii3\Inertia\Inertia exposes:
render(),location(),isInertiaRequest(),getVersion(), andnormalizeResponse().share(),getShared(),flushShared(), andreset().- Immutable
with*()methods for service configuration.
All page and prop value objects come directly from php-forge/inertia. Vite configuration, resolution, and HTML asset
rendering come directly from php-forge/vite; there is no Yii-specific Vite facade or metadata wrapper.
Adapter-owned exception text is centralized in Yii3\Inertia\Exception\Message. Exceptions from
php-forge/inertia, Yii View, and other dependencies retain their native types and messages.
Debug and telemetry packages may implement ResolvedPageObserverInterface. The observer receives the resolved core
Page synchronously and must keep captured request data request-scoped. Observation is skipped when no implementation
is bound.
See the protocol notes for header and payload details.
Documentation
For detailed configuration options and advanced usage.
- 🧪 Testing Guide