Фильтры
Фильтр — класс, код которого выполняется до контроллера или после него. До контроллера проверяют, вошёл ли посетитель и есть ли у него права; после — дополняют готовый ответ, например заголовками. Один фильтр подключают сразу ко многим адресам, и проверку не приходится повторять в каждом методе. Фильтры лежат в папке app/Filters.
Создание фильтра
php spark make:filter AuthFilterКоманда создаёт файл app/Filters/AuthFilter.php с двумя методами. Заполните первый:
// 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)
{
}
}Метод before() выполняется до контроллера. Если он возвращает ответ — здесь перенаправление, — контроллер не вызывается. Если ничего не возвращает, запрос идёт дальше.
Регистрация
Фильтру дают короткое имя в свойстве $aliases файла app/Config/Filters.php:
// app/Config/Filters.php
public array $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
// остальные строки оставьте как есть
'auth' => \App\Filters\AuthFilter::class,
];Подключение к маршруту
Имя фильтра указывают в третьем аргументе маршрута:
// app/Config/Routes.php
$routes->get('posts/new', 'Posts::new', ['filter' => 'auth']);Откройте /posts/new: в сессии нет user_id, поэтому браузер перейдёт на /login. Остальные адреса работают как прежде.
Фильтр для группы
Чтобы закрыть целый раздел, фильтр подключают к группе маршрутов:
$routes->group('admin', ['filter' => 'auth'], static function ($routes) {
$routes->get('posts', 'Admin\Posts::index');
$routes->get('users', 'Admin\Users::index');
});Все адреса, начинающиеся с /admin, проходят через фильтр.
Метод after
Метод after() получает готовый ответ и может его изменить:
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
return $response->setHeader('X-Frame-Options', 'DENY');
}Заголовок добавится ко всем ответам, прошедшим через фильтр.
Фильтры для всех запросов
Свойство $globals в app/Config/Filters.php перечисляет фильтры, которые работают на каждом адресе:
| Ключ | Когда выполняется |
|---|---|
before | До контроллера: csrf, honeypot |
after | После контроллера: toolbar, secureheaders |
Именно так в уроке о формах включалась проверка CSRF.
Частая ошибка
Фильтр auth, подключённый ко всем адресам вместе со страницей входа, создаёт бесконечное перенаправление: гость попадает на /login, фильтр снова отправляет его на /login, и браузер сообщает о слишком большом числе переходов. Подключайте фильтр только к закрытым маршрутам, а страницы входа и регистрации оставляйте открытыми.