Filters
A filter is a class whose code runs before the controller or after it. Before the controller you check whether the visitor is logged in and has permission; after it you add to the finished response, for example headers. One filter is attached to many addresses at once, so the check is not repeated in every method. Filters live in the app/Filters folder.
Creating a filter
php spark make:filter AuthFilterThe command creates the file app/Filters/AuthFilter.php with two methods. Fill in the first one:
// app/Filters/AuthFilter.php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class AuthFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
if (! session()->has('user_id')) {
return redirect()->to('/login');
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
}
}The before() method runs before the controller. If it returns a response — a redirect here — the controller is not called. If it returns nothing, the request goes on.
Registration
A filter gets a short name in the $aliases property of app/Config/Filters.php:
// app/Config/Filters.php
public array $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
// leave the other lines as they are
'auth' => \App\Filters\AuthFilter::class,
];Attaching to a route
The filter name goes into the third argument of a route:
// app/Config/Routes.php
$routes->get('posts/new', 'Posts::new', ['filter' => 'auth']);Open /posts/new: the session has no user_id, so the browser goes to /login. Other addresses work as before.
A filter for a group
To close a whole section, attach the filter to a route group:
$routes->group('admin', ['filter' => 'auth'], static function ($routes) {
$routes->get('posts', 'Admin\Posts::index');
$routes->get('users', 'Admin\Users::index');
});Every address starting with /admin passes through the filter.
The after method
The after() method receives the finished response and may change it:
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
return $response->setHeader('X-Frame-Options', 'DENY');
}The header is added to every response that passes through the filter.
Filters for all requests
The $globals property in app/Config/Filters.php lists the filters that work on every address:
| Key | When it runs |
|---|---|
before | Before the controller: csrf, honeypot |
after | After the controller: toolbar, secureheaders |
This is how the CSRF check was switched on in the forms lesson.
Common mistake
An auth filter attached to every address including the login page creates an endless redirect: a guest lands on /login, the filter sends them to /login again, and the browser reports too many redirects. Attach the filter only to protected routes and leave the login and registration pages open.