Однотипные маршруты в Laravel

143
27 декабря 2020, 17:40

В моем приложении появляется слишком много однотипных маршрутов. Разницы между ними практически нет, кроме названия контроллера и самого метода.

Например products/view_characteristics, products/view_attributes, products/view_info, products/view_photos и так далее.

Все они обрабатываются одним контроллером ProductsController.

Как мне сделать что-то на подобии такого маршрута

Route::post('{controller}/{action}', function(){
    // здесь вызываем переданный метод у переданного контроллера 
});

Есть ли в самом фреймворке такая возможность(как вариант сторонние библиотеки) или придется пилить собственные велосипеды и костыли?

Answer 1

появляется слишком много однотипных маршрутов

Вы столкнётесь с проблемой, при выполнении кэширования маршрутов php artisan route:cache:

Unable to prepare route ... for serialization. Uses Closure.

Маршруты с анонимными функциями не кэшируются.

Предположу, что метод должен быть всё таки get:

// Ресурсный маршрут должен идти перед маршрутом из вопроса.
// Чтобы не было пересечений с маршрутом `products/{id}/edit`.
Route::resource('products', 'ProductsController');
// Маршрут из вопроса.
Route::get('products/{id}/{action}', 'ProductsController@detail');

Примерная обработка метода detail в контроллере ProductsController:

public function detail(int $id, string $action)
{
  // Делаете выборку товара по $id.
  ...
  // Возвращаете один из методов контроллера.
  // Предварительно проверив его существование.
  return $this->{camel_case($action)}();
}
Answer 2

Свою проблему я решил следующим методом.

Написал функцию которая будет обрабатывать логику и вызывать нужный метод у переданного контроллера. Также в параметрах функции есть возможность указать пространство имен(если контроллер находится подкаталоге) а также для вызываемого метода префикс(это суто под себя сделал).

if (!function_exists('simple_routing')) {
    function simple_routing($controller, $action, $namespace_part, $action_prefix = '')
    {
        $namespace = '\\App\\Http\\Controllers\\' . $namespace_part . '\\' . \Illuminate\Support\Str::camel($controller) . 'Controller';
        $object = new $namespace;
        if (!method_exists($object, $action_prefix . $action)) {
            abort(404, __('common.errors.post_404'));
        }
        return app()->call([new $namespace, $action_prefix . $action]);
    }
}

Маршрут я прописывал следующим образом

Route::post('blog/{controller}/{action}', function ($controller, $action) {
    return simple_routing($controller, $action, 'Blog', 'action_');
});

По своей сути пространство имен являет собой разбиение приложения на модули. Но это так к слову.

Спасибо @Walfter за то что подтолкнул в правильном направлении.

READ ALSO
Ajax и wordpress

Ajax и wordpress

Можно ли сделать свой файл обработчик ajax, например testphp, который будет лежать в папке с темой, рядом с footer

117
Обращение к api

Обращение к api

В распоряжении имею php и js Нужно делать обращения к различным api Можно ли как то это совершать чтобы не было видно где происходит это обращение,...

118
Создание Прайс листа в Wordpress

Создание Прайс листа в Wordpress

Требуется реализовать возможность ввода данных в таблицы из админ-панели

132
Как оптимизировать sql запрос

Как оптимизировать sql запрос

Есть код, его суть - периодическое создание ордеров на продажу и покупку

134