Skip to content

Commit dbb02eb

Browse files
committed
feat: update middleware docs
1 parent a6f06b8 commit dbb02eb

File tree

1 file changed

+69
-204
lines changed

1 file changed

+69
-204
lines changed

src/docs/routing/middleware.md

Lines changed: 69 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ import VideoDocs from '/@theme/components/VideoDocs.vue'
1313

1414
## What is middleware?
1515

16-
In simple terms, middleware is a piece of code that runs before your application runs. It can be used to perform various tasks like authentication, error handling, logging, etc. It can also help to optimize the performance of an application by caching data, compressing responses, or distributing load across multiple servers, although those are more advanced use-cases. It's a great way to keep your code clean and organized.
16+
Middleware is a piece of code that runs before or after your application processes a request. It helps control the flow of requests and responses. For example, when a user visits a page on your app, you can use middleware can check if the user is logged in and if everything is okay, the request moves on to the next step; if not, the middleware can redirect the user.
1717

18-
::: tip Note
19-
Leaf has modules that can be used to perform some of the tasks middleware can do. For example, Leaf has [Leaf Auth](/modules/auth/v/2.1/) which can be used to handle authentication, a [logger module](/docs/tooling/logging) and many more useful [modules](/modules/). This means you don't need to use middleware to perform these tasks. However, middleware can be used to perform tasks that Leaf modules don't cover.
20-
:::
18+
Note that Leaf has modules that offer most of these functionalities out of the box, so you might not need to write your own middleware for them.
2119

2220
## How does middleware work?
2321

@@ -32,264 +30,131 @@ When a request is made to your application, Leaf will run through the middleware
3230
link="https://www.youtube.com/embed/Hqk9yUJfRKg"
3331
/>
3432

35-
## Middleware in Leaf
36-
37-
Leaf provides 2 interfaces for middleware: application middleware and router hooks.
38-
39-
- Router hooks basically hook into the runtime of the Leaf router and allow you to run code before a route/multiple routes are invoked.
40-
- Application middleware on the other hand is a more structured way to define and use middleware in your apps. It allows you to define middleware classes as done in other frameworks like Laravel. This fits right in if you intend to build MVC applications.
41-
42-
## Application middleware
43-
44-
As mentioned above, application middleware gives you a more structured way to define and use middleware in your apps. It allows you to define middleware as classes instead of using functions.
45-
46-
### Defining application middleware
33+
## Creating Middleware
4734

48-
Leaf provides a `Middleware` class that you can extend to define your application middleware. The `Middleware` class has a `call` method that you can override to define your middleware logic. In the `call` method, you can perform any task you want and then call `$this->next()` to pass the request to the next middleware in the stack or even return a response if you want to break the execution of your application. The example below checks if a request key is set, if it's not, the user is redirected to another route.
35+
In Leaf, middleware are just functions that are loaded into Leaf. Here's an example of a simple middleware that logs the request method and URI:
4936

5037
```php
51-
class TestMiddleware extends Leaf\Middleware
52-
{
53-
public function call()
54-
{
55-
if (!request()->get('key')) {
56-
return Custom::redirect('/login');
57-
}
58-
59-
return $this->next();
60-
}
38+
$logRequest = function () {
39+
$method = request()->method();
40+
$uri = request()->uri();
41+
42+
echo "[$method] $uri\n";
6143
}
6244
```
6345

64-
One thing to note is you should always call `$this->next()`. The `$this->next()` method forwards the incoming request to the next middleware or your application if there's no other middleware.
65-
66-
### Using your application middleware
67-
68-
After defining the middleware, the next step is to tell Leaf to actually run your middleware. You can do this by calling the `use` method on the Leaf instance.
69-
70-
<div class="class-mode">
46+
To use this middleware, you can pass it to the use() method on the Leaf instance:
7147

7248
```php
73-
$app = new Leaf\App();
74-
75-
$app->use(new TestMiddleware);
76-
77-
// ... your routes here
49+
app()->use($logRequest);
7850
```
7951

80-
</div>
81-
<div class="functional-mode">
52+
Or you can write this together:
8253

8354
```php
84-
app()->use(new TestMiddleware);
85-
86-
// ... your routes here
87-
```
88-
89-
</div>
55+
app()->use(function () {
56+
$method = request()->method();
57+
$uri = request()->uri();
9058

91-
## Before Route Middlewares
92-
93-
This is a type of router hook that runs before a particular route is invoked. It is technically just a callable/function that holds whatever code you want to execute before the route is executed. To actually create and register the before route middleware, you need to pass the function into the `before` method of the Leaf instance.
94-
95-
The `before` method takes 3 arguments:
96-
97-
- The HTTP method: This can be a single method or a pipe-separated list of methods.
98-
- The route pattern
99-
- The middleware function
100-
101-
This example below shows how to create a before route middleware that checks if a user is logged in before allowing access to the admin dashboard. Note that we're using `/admin/.*` as the route pattern. This means that the middleware will be executed for all routes that start with `/admin/`.
102-
103-
<div class="class-mode">
104-
105-
```php
106-
$app->before('GET|POST', '/admin/.*', function () {
107-
if (!isset($_SESSION['user'])) {
108-
header('location: /auth/login');
109-
exit();
110-
}
59+
echo "[$method] $uri\n";
11160
});
11261
```
11362

114-
</div>
115-
<div class="functional-mode">
63+
Using middleware this way will run the middleware for every request. If you only want to run the middleware for specific routes, you can pass the middleware as a route option.
11664

117-
```php
118-
app()->before('GET|POST', '/admin/.*', function () {
119-
if (!isset($_SESSION['user'])) {
120-
header('location: /auth/login');
121-
exit();
122-
}
123-
});
124-
```
65+
## Middleware as a route option
12566

126-
</div>
127-
128-
### Matching multiple middleware
129-
130-
Unlike route handling functions, more than one before route middleware is executed when more than one route match is found.
131-
132-
<div class="class-mode">
67+
Passing middleware as a route option will run the middleware only for that route or group of routes. You can pass a single middleware or an array of middleware to the middleware option.
13368

13469
```php
135-
$app->before('GET|POST', '/admin/.*', function () {
136-
if (!isset($_SESSION['user'])) {
137-
header('location: /auth/login');
138-
exit();
139-
}
140-
});
70+
$middleware = function () {
71+
$method = request()->method();
72+
$uri = request()->uri();
14173

142-
$app->before('GET|POST', '/admin/.*', function () {
143-
if (!isset($_SESSION['user_secret'])) {
144-
header('location: /auth/login');
145-
exit();
146-
}
147-
});
148-
```
74+
echo "[$method] $uri\n";
75+
};
14976

150-
</div>
151-
<div class="functional-mode">
77+
app()->get('/home', ['middleware' => $middleware, function () {
78+
echo 'Home page';
79+
}]);
15280

153-
```php
154-
app()->before('GET|POST', '/admin/.*', function () {
155-
if (!isset($_SESSION['user'])) {
156-
header('location: /auth/login');
157-
exit();
158-
}
159-
});
81+
app()->group('/admin', ['middleware' => $middleware, function () {
82+
app()->get('/', function () {
83+
echo 'admin dashboard';
84+
});
16085

161-
app()->before('GET|POST', '/admin/.*', function () {
162-
if (!isset($_SESSION['user_secret'])) {
163-
header('location: /auth/login');
164-
exit();
165-
}
86+
app()->get('/users', function () {
87+
echo 'admin users';
88+
});
16689
});
16790
```
16891

169-
</div>
170-
171-
Using this same concept, you can run your middleware on every route. We call this before router middleware.
172-
173-
## Before Router Middlewares
92+
This will run the $middleware function before the route handler for the /home route and all routes in the /admin group. This way, you won't have to run middleware for routes you don't need it for.
17493

175-
Before route middlewares are route specific. Using a general route pattern (viz. all URLs), they can become Before Router Middlewares (in other projects sometimes referred to as before app middlewares) which are always executed, no matter what the requested URL is.
94+
## Registering Middleware
17695

177-
<div class="class-mode">
96+
It's a bit bulky to write your middleware inline every time you need it. Leaf allows you to register middleware globally so you can use it anywhere in your app.
17897

17998
```php
180-
$app->before('GET', '/.*', function () {
181-
// ... this will always be executed
182-
});
183-
```
99+
app()->registerMiddleware('logRequest', function () {
100+
$method = request()->method();
101+
$uri = request()->uri();
184102

185-
</div>
186-
<div class="functional-mode">
187-
188-
```php
189-
app()->before('GET', '/.*', function () {
190-
// ... this will always be executed
103+
echo "[$method] $uri\n";
191104
});
192105
```
193106

194-
</div>
195-
196-
As you can see, the only difference between before route and before router middleware is the route pattern.
197-
198-
## Middleware route option
199-
200-
This is a new way to quickly setup middleware for a particular route. Leaf has the before method which allows you to set a route specific middleware, but that means defining the same route twice, not to mention, you may mistake the middleware for the main route as they have the same syntax. This problem is solved by the middleware option. **If your prefer using `before`, you can always do so.**
201-
202-
Let's take this function which we're using as our middleware:
203-
204-
```php
205-
$midfn = function () {
206-
echo 'Home middleware';
207-
};
208-
```
209-
210-
We can use this middleware directly on our route like this:
211-
212-
<div class="class-mode">
107+
We can now use this middleware in our routes:
213108

214109
```php
215-
$app->get('/home', ['middleware' => $midfn, function () {
216-
echo 'User Home';
217-
}]);
218-
```
110+
// using middleware for all routes
111+
app()->use('logRequest');
219112

220-
</div>
221-
<div class="functional-mode">
222-
223-
```php
224-
app()->get('/home', ['middleware' => $midfn, function () {
225-
echo 'User Home';
113+
// using middleware for a specific route
114+
app()->get('/home', ['middleware' => 'logRequest', function () {
115+
echo 'Home page';
226116
}]);
227-
```
228117

229-
</div>
118+
// using middleware for a group of routes
119+
app()->group('/admin', ['middleware' => 'logRequest', function () {
120+
app()->get('/', function () {
121+
echo 'admin dashboard';
122+
});
230123

231-
## Named Middleware Route Options <sup class="vt-badge">New</sup>
232-
233-
You can name your middleware and use it on multiple routes. This is useful when you have a lot of routes that use the same middleware. You can name your middleware like this:
234-
235-
<div class="class-mode">
236-
237-
```php
238-
$app->registerMiddleware('home', function () {
239-
echo 'Home middleware';
124+
app()->get('/users', function () {
125+
echo 'admin users';
126+
});
240127
});
241-
242-
$app->get('/home', ['middleware' => 'home', function () { ... }]);
243-
$app->get('/home/about', ['middleware' => 'home', function () { ... }]);
244128
```
245129

246-
</div>
130+
Notice how we passed the middleware name as a string instead of the actual function. This is because we registered the middleware with a name. This makes it easier to manage middleware in your app.
247131

248-
<div class="functional-mode">
249-
250-
```php
251-
app()->registerMiddleware('home', function () {
252-
echo 'Home middleware';
253-
});
132+
## Passing data from middleware
254133

255-
app()->get('/home', ['middleware' => 'home', function () { ... }]);
256-
app()->get('/home/about', ['middleware' => 'home', function () { ... }]);
257-
```
134+
It is necessary in some cases to pass data from middleware to the route handler. Leaf allows you to pass data from middleware to the route handler using the `response()->next()` method.
258135

259-
</div>
260-
261-
Named middleware can also be used with route groups:
136+
```php
137+
app()->registerMiddleware('logRequest', function ($next) {
138+
$method = request()->method();
139+
$uri = request()->uri();
262140

263-
<div class="class-mode">
141+
echo "[$method] $uri\n";
264142

265-
```php
266-
$app->registerMiddleware('home', function () {
267-
echo 'Home middleware';
143+
// pass data to the next handler
144+
response()->next('You can pass any value here');
268145
});
269-
270-
$app->group('/group', ['middleware' => 'home', function () use ($app) {
271-
$app->get('/home', function () { ... });
272-
$app->get('/home/about', function () { ... });
273-
}]);
274146
```
275147

276-
</div>
277-
278-
<div class="functional-mode">
148+
The data passed to the $next function will be available in the route handler:
279149

280150
```php
281-
app()->registerMiddleware('home', function () {
282-
echo 'Home middleware';
283-
});
151+
app()->get('/home', ['middleware' => 'logRequest', function () {
152+
$middlewareData = request()->next();
284153

285-
app()->group('/group', ['middleware' => 'home', function () {
286-
app()->get('/home', function () { ... });
287-
app()->get('/home/about', function () { ... });
154+
echo $middlewareData; // "You can pass any value here"
288155
}]);
289156
```
290157

291-
</div>
292-
293158
## Router Hooks
294159

295160
Hooks basically allow you to hook into Leaf router and execute a callback at a given time. For instance, you can execute a function just before Leaf fires off routes. You can also execute a callback before the main middleware executes or even after Leaf has completely executed a route.

0 commit comments

Comments
 (0)