unoptimised/inertia-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

unoptimised/inertia-bundle

Composer 安装命令:

composer require unoptimised/inertia-bundle

包简介

A Symfony bundle for Inertia.js

README 文档

README

A Symfony 5.4 / 6.4 bundle that implements the Inertia.js v1 server-side protocol, letting you build modern single-page React / Vue / Svelte apps while keeping classic Symfony routing and controllers — no REST API required.

How Inertia v1 Works (Protocol Summary)

Scenario What the server returns
First browser visit (no X-Inertia header) Full HTML page with a <div id="app" data-page="..."> mount point
Subsequent XHR navigation (X-Inertia: true) JSON page object (component, props, url, version)
Asset version mismatch (stale client) 409 Conflict with X-Inertia-Location header → client does full reload
Redirect after PUT/PATCH/DELETE 302 → 303 conversion so browser uses GET for the redirect
Partial reload (X-Inertia-Partial-Data) JSON with only the requested prop keys (plus errors always)

Installation

composer require unoptimised/inertia-bundle

Register the bundle in config/bundles.php:

return [
    // ...
    Unoptimised\InertiaBundle\UnoptimisedInertiaBundle::class => ['all' => true],
];

Configuration

Create config/packages/inertia.yaml:

inertia:
    # The Twig template used as the root layout
    root_view: 'base.html.twig'

    # Asset version — change on every deploy to force full reloads on clients
    # Can be a static string, a git SHA, or a file hash
    version: null

Dynamic version from file hash

# config/packages/inertia.yaml
inertia:
    version: '%env(resolve:ASSET_VERSION)%'

Or set it programmatically in a subscriber/listener:

$inertia->setVersion(md5_file(public_path('build/manifest.json')));

Root Layout Template

The bundle ships a minimal root template at @UnoptimisedInertia/inertia.html.twig used by default. Copy it to your own templates/ directory and point root_view at it:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>My App</title>
    <link rel="stylesheet" href="/build/app.css" />
    <script type="module" src="/build/app.js" defer></script>
</head>
<body>
    {# Renders: <div id="app" data-page="{...json...}"></div> #}
    {{ inertia(page) }}
</body>
</html>

The {{ inertia(page) }} Twig function is provided by the bundle and outputs the root <div> with the JSON-encoded page object in data-page.

Usage in Controllers

Option A — Inject Inertia directly (recommended with autowiring)

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Unoptimised\InertiaBundle\Service\Inertia;

class EventController extends AbstractController
{
    public function __construct(private readonly Inertia $inertia) {}

    #[Route('/events/{id}', name: 'events.show')]
    public function show(Event $event): Response
    {
        return $this->inertia->render('Events/Show', [
            'event' => [
                'id'          => $event->getId(),
                'title'       => $event->getTitle(),
                'description' => $event->getDescription(),
            ],
        ]);
    }
}

Shared Props

Shared props are merged into every Inertia response. Set them in a kernel event subscriber or middleware:

// src/EventSubscriber/InertiaShareSubscriber.php
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Bundle\SecurityBundle\Security;
use Unoptimised\InertiaBundle\Service\Inertia;

class InertiaShareSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly Inertia $inertia,
        private readonly Security $security,
    ) {}

    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => 'onRequest'];
    }

    public function onRequest(RequestEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }

        // Plain value
        $this->inertia->share('appName', 'My App');

        // Lazy callable — resolved only when Inertia renders a response
        $this->inertia->share('auth', function () {
            $user = $this->security->getUser();
            return $user ? ['name' => $user->getUserIdentifier()] : null;
        });

        // Multiple keys at once
        $this->inertia->share([
            'flash' => fn () => [], // wire up your flash messages here
        ]);
    }
}

Lazy Props

Pass a callable as a prop value so it is only evaluated if not excluded by a partial reload:

return $this->inertia->render('Reports/Show', [
    // Always resolved
    'title' => $report->getTitle(),

    // Only resolved when this prop is included in the response
    'data' => fn () => $this->reportService->computeHeavyData($report),
]);

Partial Reloads

The Inertia client sends X-Inertia-Partial-Data (comma-separated prop names to include) alongside X-Inertia-Partial-Component to scope the reload to a specific component. The bundle handles this transparently.

X-Inertia-Partial-Component: Events/Index
X-Inertia-Partial-Data: events,filters   ← only return these props

Validation Errors

Symfony's form validation errors should be placed under the errors key in props. A common pattern using Symfony's ValidatorInterface:

$errors = [];
$violations = $this->validator->validate($dto);
foreach ($violations as $violation) {
    $field = $violation->getPropertyPath();
    $errors[$field] = $violation->getMessage();
}

return $this->inertia->render('User/Edit', [
    'user'   => $dto,
    'errors' => $errors,
]);

The Inertia client automatically makes validation errors available to your form components.

Asset Versioning

Set inertia.version in config (or call $inertia->version(...) at runtime). On every request the bundle compares the client-sent X-Inertia-Version header against the server version. If they differ the bundle returns:

HTTP/1.1 409 Conflict
X-Inertia-Location: https://example.com/current-url

The Inertia JS client then performs a full page reload to pick up new assets.

Redirect Behaviour

Method Server 302 What Inertia sees
GET 302 302 (unchanged)
PUT / PATCH / DELETE 302 303 (converted by listener)

The 302→303 conversion is handled automatically by InertiaListener::onKernelResponse().

Running Tests

composer install
./vendor/bin/phpunit

unoptimised/inertia-bundle 适用场景与选型建议

unoptimised/inertia-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 207 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 03 月 03 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 unoptimised/inertia-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 unoptimised/inertia-bundle 我们能提供哪些服务?
定制开发 / 二次开发

基于 unoptimised/inertia-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 207
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-03