Installation
composer require dderenko/inertia-bundle
Add the bundle to config/bundles.php:
return [
// ...
Dderenko\InertiaBundle\InertiaBundle::class => ['all' => true],
];
Basic Configuration
Edit config/packages/dderenko_inertia.yaml to define your Inertia entry point:
inertia:
entry: 'public/js/app.js' # Path to your Inertia.js entry file
First Use Case: Rendering a Page
In a Symfony controller, use the render method:
use Dderenko\InertiaBundle\Inertia\Inertia;
class DashboardController extends AbstractController
{
public function index(Inertia $inertia)
{
return $inertia->render('Dashboard', [
'user' => $this->getUser(),
'stats' => $this->getStats(),
]);
}
}
Verify Setup
public/js/app.js is correctly configured with Inertia.js.Reusable Render Logic Create a base controller to centralize Inertia rendering:
abstract class InertiaController extends AbstractController
{
protected function renderInertia(string $page, array $props = [])
{
return $this->inertia->render($page, $props);
}
}
Dynamic Page Resolution Use Symfony’s dependency injection to fetch pages dynamically:
public function show(Inertia $inertia, string $page, array $props)
{
return $inertia->render($page, $props);
}
Type Safety
Define props in your Vue/React components with PropTypes or TypeScript interfaces. Validate in PHP using Symfony’s Assert:
use Symfony\Component\Validator\Constraints as Assert;
public function index(Inertia $inertia)
{
$props = [
'user' => $this->getUser(),
'settings' => new Assert\Collection([
'newNotifications' => new Assert\Type('bool'),
]),
];
return $inertia->render('Settings', $props);
}
Shared Props
Use Symfony’s ParameterBag or a service to share props across controllers:
# config/services.yaml
services:
App\Service\SharedProps:
arguments:
$props: '%kernel.project_dir%/config/inertia_shared_props.php'
Named Routes Combine with Symfony’s router for clean URLs:
// routes.yaml
dashboard:
path: /dashboard
controller: App\Controller\DashboardController::index
methods: GET
// Vue/React
this.$inertia.visit('/dashboard'); // Uses Symfony's router
API + Inertia Hybrid Use the same controller for both API and Inertia responses:
public function index(Request $request, Inertia $inertia)
{
if ($request->isXmlHttpRequest()) {
return json_response($this->getData());
}
return $inertia->render('Dashboard', $this->getData());
}
Vite/Webpack Integration
Ensure your build tool outputs to public/build/ and update inertia.entry:
inertia:
entry: 'build/app.js'
Hot Reloading
Configure your frontend tool to watch templates/ for changes and auto-update Inertia pages.
Missing Entry Point
Uncaught ReferenceError: Inertia is not definedinertia.entry in config points to a valid file (e.g., public/js/app.js).CORS Issues
inertia->share() for global props:
$inertia->share(['auth' => $this->getAuthUser()]);
Prop Serialization
->toArray() or custom serializers:
use Symfony\Component\Serializer\SerializerInterface;
public function index(SerializerInterface $serializer, Inertia $inertia)
{
$props = $serializer->serialize($this->getData(), 'json');
return $inertia->render('Page', json_decode($props, true));
}
CSRF Token Mismatch
419 | Page Expired on form submissions.$inertia->share(['csrf_token' => $this->container->get('security.csrf.token_manager')->getToken('main')->getValue()]);
Log Inertia Responses Temporarily log the rendered JSON in a controller:
$response = $inertia->render('Page', $props);
$this->logger->debug('Inertia Response:', ['data' => $response->getContent()]);
Check Headers Ensure responses include:
Content-Type: application/json
X-Inertia: true
Custom Responses
Extend the InertiaResponse class to add middleware or headers:
namespace App\Inertia;
use Dderenko\InertiaBundle\Inertia\InertiaResponse;
class CustomInertiaResponse extends InertiaResponse
{
public function setCustomHeader(string $name, string $value)
{
$this->headers->set($name, $value);
}
}
Bind it in services.yaml:
services:
App\Inertia\CustomInertiaResponse:
tags: ['inertia.response']
Page Resolution Override page resolution to fetch templates from a custom location:
// config/packages/dderenko_inertia.yaml
inertia:
page_resolver: App\Inertia\CustomPageResolver
Shared State Use Symfony’s event system to share state across requests:
// src/EventListener/InertiaShareListener.php
public function onKernelRequest(GetResponseEvent $event)
{
$inertia = $event->getRequest()->attributes->get('inertia');
$inertia->share(['theme' => $this->getTheme()]);
}
Lazy-Loading Props Fetch props asynchronously in Vue/React:
// Vue
created() {
this.$inertia.get(this.$page.props.url, {}, {
only: ['data'], // Only fetch specific props
});
}
Cache Inertia Responses Cache shared props or entire responses for static pages:
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Cache\CacheInterface;
public function index(CacheInterface $cache, Inertia $inertia)
{
$cacheKey = 'inertia:dashboard';
if ($cached = $cache->get($cacheKey)) {
return new Response($cached, 200, ['Content-Type' => 'application/json']);
}
$response = $inertia->render('Dashboard', $props);
$cache->set($cacheKey, $response->getContent(), 3600);
return $response;
}
How can I help you explore Laravel packages today?