-
Notifications
You must be signed in to change notification settings - Fork 0
Usage
Use this InertiaJS library in your own PHP project and create a Single-Page Application hassle-free.
To be able to use InertiaJS, create a Response Factory that returns an appropriate response based on whether Inertia is being loaded or not. Abstract protected methods accept a response object that is provided by the last middleware as part of the request/response cycle.
The Request Handler's response must include the Inertia middleware's Response headers. If your project does not facilitate such a feature, use Pipeline Bridge.
Eg: In PHP file named InertiaResponseFactory.php
that contains InertiaResponseFactory class:
use Psr\Http\Message\ResponseInterface;
use TheWebSolver\Codegarage\Lib\Inertia\ResponseFactory;
class InertiaResponseFactory extends ResponseFactory {
/**
* Ensures that first request will paint the Browser DOM with full HTML page.
*
* Response should follow these implementations.
* - The header may have Content-Type as `text/html` or similar.
*/
protected function html( ResponseInterface $previous ): ResponseInterface {
return $previous
->withHeader('Content-Type', 'text/html')
->withBody((new StreamFactory())->createStream(
htmlspecialchars(
string: json_encode( data: $this->body ),
flags: ENT_QUOTES,
encoding: 'UTF-8',
double_encode: true
)
));
}
/**
* Ensures subsequent request will only need to provide client-side props and no more server-side reloads.
*
* Response should follow these implementations.
* - The header must have Content-Type as `application/json`.
* - The response must return a JSON encoded string when
* `$response->getBody()->getContents()` is called.
*/
protected function json( ResponseInterface $previous ): ResponseInterface {
return $previous
->withHeader('Content-Type', 'application/json')
->withBody((new StreamFactory())->createStream(json_encode($this->body)));
}
}
In your project's root file:
If your project has app Container that implements Psr\Container\ContainerInterface
, set binding using it. We'll assume that app container supports singleton design pattern. If it does not, use Option 2.
use TheWebSolver\Codegarage\Lib\Inertia\Adapter;
use TheWebSolver\Codegarage\Lib\Inertia\ResponseFactory;
// Inject container to Inertia app. Here "$appContainer" is your project container.
Adapter::setApp( app: $appContainer );
// Bind your custom InertiaResponseFactory to the abstract ResponseFactory as a singleton.
$appContainer->singleton(
abstract: ResponseFactory::class,
concrete: InertiaResponseFactory::class
);
Inject factory directly to the Inertia app.
use TheWebSolver\Codegarage\Lib\Inertia\Inertia;
Inertia::setFactory( classname: InertiaResponseFactory::class );
If any external task needs to be handled when middleware is processed, you can pass a subscriber. Most use case would be to add bundled script so InertiaJS works as intended.
use TheWebSolver\Codegarage\Lib\Inertia\Inertia;
Inertia::subscribe(
subscriber: static fn() => '<script src="path/to/bundled/inertia.js">'
);
Let's use the following Route and its action callback as an example:
- The route's action Closure (lambda function) is accepted by your request handler's constructor as a fallback.
- The request handler handles all the middleware and invokes the route action Closure with the
$request
and the last middleware's$response
. - These
$request
and$response
args are passed throughInertia::render()
API, which are accepted byInertiaResponseFactory
's abstract methods. Then, the final response is returned.
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TheWebSolver\Codegarage\Lib\Inertia\Inertia;
use TheWebSolver\Codegarage\Lib\Inertia\Middleware;
// Optional. Custom path to default root view. If not provided, it will search for php file named "inertia".
$view = 'path/to/first/loaded/by/server/templateFile.php';
Route::get('/posts/', action: function(ServerRequestInterface $request, ResponseInterface $response) {
// Props are required.
$posts = array();
return Inertia::render($request, $response, component: 'posts', props: compact('posts'));
} )->middleware(new Middleware()->set(version: 'usuallyScriptVersion', rootView: $view));
