PHPackages                             tinymvc/inertia-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. tinymvc/inertia-php

ActiveLibrary[Framework](/categories/framework)

tinymvc/inertia-php
===================

A simple and lightweight PHP library for building Inertia.js applications.

v1.0.0(4mo ago)21511MITPHP

Since Feb 18Pushed 4mo agoCompare

[ Source](https://github.com/tinymvc/inertia-php)[ Packagist](https://packagist.org/packages/tinymvc/inertia-php)[ RSS](/packages/tinymvc-inertia-php/feed)WikiDiscussions main Synced today

READMEChangelog (1)DependenciesVersions (2)Used By (1)

Inertia.js PHP Adapter for TinyMVC
==================================

[](#inertiajs-php-adapter-for-tinymvc)

A server-side adapter for [Inertia.js](https://inertiajs.com) v2, enabling you to build modern single-page applications using classic server-side routing and controllers.

Inertia eliminates the complexity of building SPAs. There's no need for client-side routing, API endpoints, or data fetching logic. Simply build controllers and page views like you've always done.

Installation
------------

[](#installation)

```
composer require tinymvc/inertia-php
```

Setup
-----

[](#setup)

Register the service provider in your application:

```
// bootstrap/providers.php
return [
    \Inertia\InertiaServiceProvider::class,
];
```

The service provider automatically registers:

- The `Inertia` singleton
- The `@inertia` Blade directive
- The `Route::inertia()` router macro

Basic Usage
-----------

[](#basic-usage)

There are multiple ways to create Inertia responses:

### Using the Inertia Class

[](#using-the-inertia-class)

```
use Inertia\Facades\Inertia;

class UsersController
{
    public function index()
    {
        return Inertia::render('Users/Index', [
            'users' => User::all(),
        ]);
    }
}
```

### Using the Helper Function

[](#using-the-helper-function)

The `inertia()` helper provides a convenient shorthand:

```
class UsersController
{
    public function index()
    {
        // Render a component with props
        return inertia('Users/Index', [
            'users' => User::all(),
        ]);
    }

    public function show(User $user)
    {
        // Access Inertia instance without rendering
        $inertia = inertia();
        $inertia->setRootView('layouts.admin');

        return $inertia->render('Users/Show', [
            'user' => $user,
        ]);
    }
}
```

### Using Route Macro

[](#using-route-macro)

For simple pages that don't require a controller, use the `Route::inertia()` macro:

```
// routes/web.php
use Spark\Facades\Route;

Route::inertia('/', 'Home');
Route::inertia('/about', 'About', ['version' => '1.0.0']);
Route::inertia('/contact', 'Contact');
```

This is equivalent to:

```
Route::get('/', fn() => inertia('Home'));
```

Root Template
-------------

[](#root-template)

Create a root Blade template that will load your JavaScript application:

```

    My App
    @vite('app.tsx')

    @inertia

```

The `@inertia` Blade directive renders a `` element with a `data-page` attribute containing the page data:

```

```

### Custom Root View

[](#custom-root-view)

By default, Inertia uses the `app` view. To change it:

```
Inertia::setRootView('layouts.admin');
```

Sharing Data
------------

[](#sharing-data)

Share data globally across all Inertia responses. This is useful for data like the authenticated user, flash messages, or application settings.

```
// In a middleware or service provider
use Inertia\Facades\Inertia;

// Share a single value
Inertia::share('appName', config('app.name'));

// Share multiple values
Inertia::share([
    'auth' => [
        'user' => auth()->user(),
    ],
    'flash' => [
        'success' => session('success'),
        'error' => session('error'),
    ],
    'locale' => app()->getLocale(),
]);

// Retrieve shared data
$appName = Inertia::getShared('appName');
$allShared = Inertia::getShared(); // Returns all shared data
```

Props
-----

[](#props)

Props are the data passed to your page components. Inertia supports various prop types for different use cases.

### Standard Props

[](#standard-props)

Regular props are always included in responses:

```
return inertia('Users/Index', [
    'users' => User::all(),
    'filters' => $request->only(['search', 'status']),
]);
```

### Lazy Evaluation with Closures

[](#lazy-evaluation-with-closures)

Wrap props in closures for lazy evaluation. The closure is only executed when the prop is actually needed:

```
return inertia('Dashboard', [
    // Always evaluated
    'user' => $user,

    // Only evaluated when included in response
    'users' => fn () => User::all(),
    'companies' => fn () => Company::all(),
]);
```

### Optional Props

[](#optional-props)

Optional props are never included in the initial response. They must be explicitly requested via partial reloads:

```
return inertia('Reports', [
    'summary' => $summary,

    // Only loaded when explicitly requested
    'detailedReport' => Inertia::optional(fn () => Report::generateDetailed()),
]);
```

Client-side request:

```
router.reload({ only: ['detailedReport'] })
```

### Always Props

[](#always-props)

Always props are included in every response, even during partial reloads when not explicitly requested:

```
return inertia('Dashboard', [
    'users' => fn () => User::all(),

    // Always fresh, even in partial reloads
    'notifications' => Inertia::always(fn () => auth()->user()->unreadNotifications),
    'flash' => Inertia::always(fn () => session('flash')),
]);
```

Deferred Props
--------------

[](#deferred-props)

Deferred props are excluded from the initial page load and loaded in a subsequent request after the page renders. This improves perceived performance for pages with expensive data.

```
return inertia('Dashboard', [
    // Loaded immediately
    'user' => $user,

    // Loaded after page renders
    'stats' => Inertia::defer(fn () => Stats::calculate()),
    'recentActivity' => Inertia::defer(fn () => Activity::recent()),
]);
```

### Grouping Deferred Props

[](#grouping-deferred-props)

Group related deferred props to load them in a single request:

```
return inertia('Dashboard', [
    // Default group - separate request
    'permissions' => Inertia::defer(fn () => Permission::all()),

    // 'sidebar' group - loaded together in one request
    'teams' => Inertia::defer(fn () => Team::all(), 'sidebar'),
    'projects' => Inertia::defer(fn () => Project::all(), 'sidebar'),

    // 'charts' group - another separate request
    'salesChart' => Inertia::defer(fn () => Chart::sales(), 'charts'),
    'trafficChart' => Inertia::defer(fn () => Chart::traffic(), 'charts'),
]);
```

Merge Props
-----------

[](#merge-props)

Merge props append or prepend data to existing client-side data instead of replacing it. Perfect for infinite scrolling, real-time feeds, and pagination.

### Append (Default)

[](#append-default)

```
return inertia('Feed', [
    // New items are appended to existing items
    'posts' => Inertia::merge(fn () => Post::paginate(10)),
]);
```

### Prepend

[](#prepend)

```
return inertia('Chat', [
    // New messages appear at the top
    'messages' => Inertia::prepend(fn () => Message::latest()->take(20)->get()),
]);
```

### Deep Merge

[](#deep-merge)

For nested objects where you want to merge at all levels:

```
return inertia('Settings', [
    'config' => Inertia::deepMerge(fn () => [
        'notifications' => ['email' => true],
        'privacy' => ['showProfile' => false],
    ]),
]);
```

### Deduplication

[](#deduplication)

Prevent duplicate items when merging by specifying a match key:

```
return inertia('Feed', [
    // Match by 'id' field to avoid duplicates
    'posts' => Inertia::merge(fn () => Post::paginate())->matchOn('id'),
]);
```

Once Props
----------

[](#once-props)

Once props are evaluated and sent only once. On subsequent page visits, the client reuses the cached value, reducing server load for static or rarely-changing data.

```
return inertia('Settings', [
    // Fetched once, then cached on client
    'countries' => Inertia::once(fn () => Country::all()),
    'timezones' => Inertia::once(fn () => Timezone::all()),
]);
```

### Expiration

[](#expiration)

Set an expiration time after which the prop will be re-fetched:

```
return inertia('Dashboard', [
    // Refresh after 1 day
    'exchangeRates' => Inertia::once(fn () => ExchangeRate::all())
        ->until(now()->addDay()),

    // Refresh after 1 hour (using seconds)
    'weather' => Inertia::once(fn () => Weather::current())
        ->until(3600),
]);
```

### Custom Keys

[](#custom-keys)

Share once props across different pages using custom keys:

```
// On Team/Index page
return inertia('Team/Index', [
    'memberRoles' => Inertia::once(fn () => Role::all())->as('roles'),
]);

// On Team/Invite page - reuses the same cached data
return inertia('Team/Invite', [
    'availableRoles' => Inertia::once(fn () => Role::all())->as('roles'),
]);
```

### Force Refresh

[](#force-refresh)

Force a prop to be re-fetched even if cached:

```
return inertia('Billing', [
    'plans' => Inertia::once(fn () => Plan::all())->fresh(),

    // Conditional refresh
    'features' => Inertia::once(fn () => Feature::all())->fresh($planChanged),
]);
```

### Global Once Props

[](#global-once-props)

Share once props across all pages:

```
// In a service provider or middleware
Inertia::shareOnce('countries', fn () => Country::all());
Inertia::shareOnce('config', fn () => AppConfig::all())->until(now()->addHour());
```

Chaining Modifiers
------------------

[](#chaining-modifiers)

Combine prop types for advanced behavior:

```
return inertia('Dashboard', [
    // Load after render, then cache
    'stats' => Inertia::defer(fn () => Stats::generate())->once(),

    // Merge new data, then cache
    'activity' => Inertia::merge(fn () => $user->recentActivity())->once(),

    // Only load when requested, then cache
    'reports' => Inertia::optional(fn () => Report::all())->once(),

    // Defer loading, then merge with existing data
    'notifications' => Inertia::defer(fn () => Notification::paginate())->merge(),
]);
```

History Encryption
------------------

[](#history-encryption)

Encrypt the page data stored in browser history to protect sensitive information after logout.

### Per-Request Encryption

[](#per-request-encryption)

```
// Enable encryption for this response
return inertia()
    ->withEncryptedHistory()
    ->render('Account/Settings', $props);
```

### Clear History

[](#clear-history)

Clear previously encrypted history entries (useful after logout):

```
return inertia()
    ->withClearedHistory()
    ->render('Auth/Login');
```

Redirects
---------

[](#redirects)

Inertia handles redirects intelligently, maintaining SPA behavior.

### Standard Redirects

[](#standard-redirects)

```
public function store(Request $request)
{
    User::create($request->validated());

    return inertia()->redirect('/users');
}
```

### Back Redirect

[](#back-redirect)

```
public function update(Request $request, User $user)
{
    $user->update($request->validated());

    return inertia()->back();
}
```

### External Redirects

[](#external-redirects)

For redirects to external URLs or non-Inertia pages:

```
return inertia()->location('https://external-site.com');
return inertia()->location('/non-inertia-page');
```

> **Note:** Inertia automatically uses 303 status codes for redirects after PUT, PATCH, or DELETE requests to prevent browser confirmation dialogs.

View Composers
--------------

[](#view-composers)

View composers run before specific components are rendered, allowing you to attach data dynamically.

```
// Single component
Inertia::composer('Dashboard', function ($inertia) {
    Inertia::share([
        'dashboardStats' => Stats::forDashboard(),
    ]);
});

// Multiple components
Inertia::composer(['Users/Index', 'Users/Show', 'Users/Edit'], function ($inertia) {
    Inertia::share([
        'roles' => Role::all(),
        'departments' => Department::all(),
    ]);
});

// All components (useful for global data)
Inertia::composer('*', function ($inertia) {
    Inertia::share([
        'appVersion' => config('app.version'),
        'currentYear' => date('Y'),
    ]);
});
```

Asset Versioning
----------------

[](#asset-versioning)

Inertia uses asset versioning to ensure clients always have the latest assets. When assets change, Inertia triggers a full page reload.

By default, the adapter uses the Vite manifest file hash:

```
// Automatic (default behavior)
// Uses: public/build/.vite/manifest.json
```

### Custom Version

[](#custom-version)

```
$inertia = Inertia::instance();

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

// Using deployment timestamp
$inertia->setVersion(config('app.deploy_version'));

// Using git commit hash
$inertia->setVersion(exec('git rev-parse --short HEAD'));
```

API Reference
-------------

[](#api-reference)

MethodDescription`Inertia::instance()`Get the Inertia Adapter Instance`Inertia::render($component, $props)`Render an Inertia response`Inertia::redirect($url, $status)`Create a redirect response`Inertia::back($status)`Redirect to previous page`Inertia::location($url)`External redirect (409 response)`Inertia::setRootView($view)`Set the root Blade template`Inertia::setVersion($version)`Set the asset version`Inertia::withEncryptedHistory($encrypt)`Enable history encryption`Inertia::withClearedHistory($clear)`Clear encrypted history`Inertia::share($key, $value)`Share data globally`Inertia::getShared($key, $default)`Retrieve shared data`Inertia::shareOnce($key, $callback)`Share a once prop globally`Inertia::flushShared()`Clear all shared data`Inertia::forceRefresh()`Force the client to reload the page`Inertia::composer($components, $callback)`Register a view composer`Inertia::lazy($callback)`Create a lazy prop`Inertia::optional($callback)`Create an optional prop`Inertia::always($callback)`Create an always prop`Inertia::defer($callback, $group)`Create a deferred prop`Inertia::merge($callback)`Create a merge prop (append)`Inertia::prepend($callback)`Create a merge prop (prepend)`Inertia::deepMerge($callback)`Create a deep merge prop`Inertia::once($callback)`Create a once prop### Helper Function

[](#helper-function)

FunctionDescription`inertia()`Get the Inertia instance`inertia($component, $props)`Render an Inertia response### Blade Directive

[](#blade-directive)

DirectiveDescription`@inertia`Render the root element with page data### Router Macro

[](#router-macro)

MethodDescription`Route::inertia($path, $component, $props)`Register an Inertia routeLicense
-------

[](#license)

MIT

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance75

Regular maintenance activity

Popularity10

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 83.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

137d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f6904c684048421da96c056bc3b6dc0c1bbf58f847454a6b927bbc26da41ebe7?d=identicon)[dev.shahin](/maintainers/dev.shahin)

---

Top Contributors

[![shahinmoyshan](https://avatars.githubusercontent.com/u/128284645?v=4)](https://github.com/shahinmoyshan "shahinmoyshan (5 commits)")[![tinymvc](https://avatars.githubusercontent.com/u/177845414?v=4)](https://github.com/tinymvc "tinymvc (1 commits)")

### Embed Badge

![Health badge](/badges/tinymvc-inertia-php/health.svg)

```
[![Health](https://phpackages.com/badges/tinymvc-inertia-php/health.svg)](https://phpackages.com/packages/tinymvc-inertia-php)
```

###  Alternatives

[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k39.6M299](/packages/laravel-dusk)[nineinchnick/edatatables

Grid widget for the Yii Framework, wrapper for the DataTables jQuery plugin

173.2k](/packages/nineinchnick-edatatables)[link-cloud/fast-hyperf

LinkCloud Fast Hyperf

241.2k1](/packages/link-cloud-fast-hyperf)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
