Simplify Routing in Laravel with Laravel Folio Package
If you're a developer working with Laravel applications, you know how important it is to handle routing efficiently. The good news is that there's a powerful solution to simplify routing in Laravel—Laravel Folio! In this blog post, we'll introduce you to this amazing package and show you how easy it is to work with it.
Introduction
Laravel Folio is a page-based router specifically designed to streamline routing in Laravel applications. With this package, generating a route becomes as effortless as creating a Blade template within your application's resources/views/pages
directory.
For instance, let's say you want to create a page accessible at /greeting
. You can achieve this by simply creating a greeting.blade.php
file in your application's resources/views/pages
directory:
<div>
Hello World
</div>
Installation
Getting started with Folio is a breeze. You can install it into your project using the Composer package manager:
composer require laravel/folio:^1.0@beta
Once installed, execute the folio:install
Artisan command, which will register Folio's service provider into your application and set up the directory where Folio will search for routes/pages:
php artisan folio:install
Creating Routes
Creating a Folio route is simple. Just place a Blade template in any of your Folio-mounted directories. By default, Folio mounts the resources/views/pages
directory, but you can customize these directories in your Folio service provider's boot
method.
Once you've placed a Blade template in a Folio-mounted directory, you can immediately access it via your browser. For example, if you place a page in pages/schedule.blade.php
, you can access it in your browser at http://example.com/schedule
.
Nested Routes
If you need to create a nested route, you can do so by creating one or more directories within one of Folio's directories. For example, to create a page accessible via /user/profile
, create a profile.blade.php
template within the pages/user
directory:
php artisan make:folio user/profile
# pages/user/profile.blade.php → /user/profile
Index Routes
Sometimes, you may want to make a page the "index" of a directory. By placing an index.blade.php
template within a Folio directory, any requests to the root of that directory will be routed to that page:
php artisan make:folio index
# pages/index.blade.php → /
php artisan make:folio users/index
# pages/users/index.blade.php → /users
Route Parameters
Often, you'll need to have segments of the incoming request's URL injected into your page so you can interact with them. To achieve this, you can encapsulate a segment of the page's filename in square brackets:
php artisan make:folio "users/[id]"
# pages/users/[id].blade.php → /users/1
Captured segments can be accessed as variables within your Blade template:
<div>
User {{ $id }}
</div>
To capture multiple segments, you can prefix the encapsulated segment with three dots ...
:
php artisan make:folio "user/[...ids]"
# pages/users/[...ids].blade.php → /users/1/2/3
When capturing multiple segments, the captured segments will be injected into the page as an array:
<ul>
@foreach ($ids as $id)
<li>User {{ $id }}</li>
@endforeach
</ul>
Route Model Binding
If a wildcard segment of your page template's filename corresponds to one of your application's Eloquent models, Folio will automatically take advantage of Laravel's route model binding capabilities and attempt to inject the resolved model instance into your page:
php artisan make:folio "user/[User]"
# pages/users/[User].blade.php → /users/1
Captured models can be accessed as variables within your Blade template. The model's variable name will be converted to "camel case":
<div>
User {{ $user->id }}
</div>
Customizing The Key
You can also customize the key used for resolving Eloquent models. Simply specify the column in the page's filename. For example, a page with the filename [Post:slug].blade.php
will attempt to resolve the bound model via the slug
column instead of the id
column.
Model Location
By default, Folio searches for your model within your application's app/Models
directory. However, you can specify the fully-qualified model class name in your template's filename if needed:
php artisan make:folio "user/[.App.Models.User]"
# pages/users/[.App.Models.User].blade.php → /users/1
Soft Deleted Models
By default, soft-deleted models are not retrieved when resolving implicit model bindings. However, if you wish, you can instruct Folio to retrieve soft-deleted models by invoking the withTrashed
function within the page's template:
<?php
use function Laravel\Folio\{withTrashed};
withTrashed();
?>
<div>
User {{ $user->id }}
</div>
Middleware
Applying middleware to a specific page is straightforward. Simply invoke the middleware
function within the page's template:
<?php
use function Laravel\Folio\{middleware};
middleware(['auth']);
?>
<div>
Dashboard
</div>
Alternatively, you can assign middleware to a group of pages by providing the middleware
argument when invoking the Folio::route
method.
You can specify which pages the middleware should be applied to by keying the array of middleware using the corresponding URL patterns of the pages they should be applied to. The *
character can be used as a wildcard:
use Laravel\Folio\Folio;
Folio::route(resource_path('views/pages'), middleware: [
'chirps/*' => [
'auth',
// ...
],
]);
You may also include closures in the array of middleware to define inline, anonymous middleware:
use Closure;
use Illuminate\Http\Request;
use Laravel\Folio\Folio;
Folio::route(resource_path('views/pages'), middleware: [
'chirps/*' => [
'auth',
function (Request $request, Closure $next) {
// ...
return $next($request);
},
],
]);
PHP Blocks
When using Folio, the <?php
and ?>
tags are reserved for Folio's page definition functions such as middleware
and withTrashed
.
Therefore, if you need to write PHP code that should be executed within your Blade template, use the @php
Blade directive:
@php
if (! Auth::user()->can('view-posts', $user)) {
abort(403);
}
$
posts = $user->posts;
@endphp
@foreach ($posts as $post)
<div>
{{ $post->title }}
</div>
@endforeach