Настройка соответствия контроллер/метод для HLEB2 аналогично роутингу Yii2

06 Июня (ред)

В YII2 (да и не только в нём) по умолчанию маршруты автоматически распределяются по контроллерам и методам. Например, адрес /site/index будет указывать в контроллер SiteController и его метод actionIndex(). С одной стороны это удобно, но способствует тому, что разработчики делают огромные контроллеры со множеством методов, что встречается почти в каждом проекте на YII. В совокупности с неинтуитивным роутингом в YII такое автоназначение маршрутов используется повсеместно, но многие привыкают к такому способу и он кажется более удобным.

Во фреймворке HLEB2 достаточно гибкий роутинг, но если вам все же хочется использовать его аналогично устроенному в YII2 - следующая инструкция объясняет как.

Во фрейморке YII2 в корне проекта можно создавать так называемые приложения, для каждого своя папка с контроллерами и представлениями. Во фреймворке HLEB2 для этого допустимо создать отдельный модуль. Выполним команду, которая создаст модуль:

php console --create module common

Команда создаст базовую составляющую модуля - конфигурацию, контроллер и представление.

В реальности оставлять название контроллеру DefaultModuleController не красиво, поэтому переименую его в SiteController, аналогично примеру для YII выше.

Теперь нужно добавить в маршрут фреймворка такое условие:

// Файл /routes/main.php
Route::any('/{controller}/{method}')
    ->module('common', 'Modules\Common\Controllers\<controller>Controller@<method>');

Теперь, если в браузере добавить к адресу ресурса '/site/index' то будет выполнен указанный контроллер с методом и как результат будет вывод текста из представления.

Но для YII в самом контроллере реализована проверка HTTP-метода запроса. Попробуем реализовать и это, хотя сам принцип аналогичной маршрутизации уже сделан. Предварительно нужно сделать базовый контроллер, от которого будут наследоваться все контроллеры такого типа.

<?php
// Файл /modules/common/controllers/BaseController.php
declare(strict_types=1);

namespace Modules\Common\Controllers;

use Hleb\Base\Controller;
use Hleb\Http404NotFoundException;
use Hleb\Reference\Interface\Request;

abstract class BaseController extends Controller
{
    abstract protected function rules(): array;

    public function __construct(Request $request, $config = [])
    {
        parent::__construct($config);

        $method = $request->param('method')?->asString();
        if (!in_array($request->getMethod(), $this->rules()[$method] ?? [], true)) {
            throw new Http404NotFoundException();
        }
    }
}

В этом классе объявлен абстрактный метод rules(), который должен быть в наследуемых контроллерах, он будет возвращать список поддерживаемых HTTP-методов. Добавим этот метод в используемый класс и унаследуем его от BaseController.

<?php
// Файл /modules/common/controllers/SiteController.php
namespace Modules\Common\Controllers;

use Hleb\Constructor\Data\View;

class SiteController extends BaseController
{
    protected function rules(): array
    {
        return [
            'index' => ['POST', 'GET'],
        ];
    }

    public function index(): View
    {
        return view("example");
    }
}

Теперь в контроллерах модуля можно указывать типы поддерживаемых HTTP-методов для каждого метода контроллера, а запросы автоматически находят контроллер и метод.

Внимание! Этот вид маршрутизации требует особого внимания к публичным методам контроллеров, так как все они могут быть вызваны пользователем.

Полезная информация: при таком способе адрес /example-site/example-index будет направлен в метод exampleIndex() для класса Modules\Common\Controllers\ExampleSiteController.

fomiash fomiash + 215
Опубликовано в PHP фреймворк HLEB

3 Ответа

  1. Evg Evg 06 Июня

    Интересно, спасибо!

  1. fomiash fomiash 07 Июня

    Часть подобных статей вынес в раздел "Вопросы", с недавнего времени он также пополняется категорией FAQ, так что велком.

  1. fomiash fomiash 07 Июня (ред.)

    UPD Если изменить маршрут на:

    // Файл /routes/main.php
    Route::any('/{controller}/{method}')
        ->module('common', 'Modules\Common\Controllers\<controller>Controller@action<method>');

    то будет более полная подстройка под Yii2, так как теперь только методы контроллера начинающиеся с "action" будут участвовать в подборе совпадений. Например, адрес /site/index будет указывать в контроллер модуля SiteController и его метод actionIndex(). При этом в rules() останется по прежнему ключ 'index' в данном случае.



Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.