Игнорировать маршрут в Laravel 5.1

Я хочу создать динамические страницы CMS для своего приложения Laravel. Администратору разрешено указывать любой URI для любой страницы, например, он может создать страницу с one/two/three URI и http://example.com/one/two/three будет указывать на этот сайт. Я уже понял, что можно добавить один маршрут для нескольких URL-адресов уровня, например:

get('{uri}', 'PageController@view')->where('uri', '.+');

Теперь я также хочу, чтобы /{username} URL-адреса указывали на профили пользователей. Это означает, если мне нужно, чтобы это работало вместе. Для меня идеальным кодом было бы что-то вроде этого:

get('{username}', 'ProfileController@view');
get('{uri}', 'PageController@view')->where('uri', '.+');

Затем в ProfileController я хотел бы, чтобы мой маршрут шел дальше, как будто его там не было. Что-то вроде этого:

// ProfileController

public function view()
{
    $user = User::whereUsername($username)->first();

    if ($user === null) {
        // Go to the next route.
    }
}

Можно ли это сделать с помощью Laravel?

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


person Robo Robok    schedule 18.09.2015    source источник
comment
Я бы просто добавил префикс типа /users к вашему маршруту ProfileController   -  person peaceman    schedule 18.09.2015
comment
@peaceman Я знаю, что это упростит задачу, но я действительно хочу сохранить маршруты /{username}.   -  person Robo Robok    schedule 18.09.2015
comment
Не могли бы вы создать php-файл со всеми маршрутами, определенными администратором, и включить его перед маршрутом ProfileController? Это также должно ускорить процесс маршрутизации.   -  person peaceman    schedule 18.09.2015


Ответы (1)


Вы можете разрешить новый экземпляр PageController из сервисного контейнера, если $user равно null.

// ProfileController

public function view()
{
    $user = User::whereUsername($username)->first();

    if ($user === null) {
        // Go to the next route.
        $params = []; // If your view method on the PageController has any parameters, define them here
        $pageController = app(PageController::class);
        return $pageController->callAction('view', $params)
    }
}

Таким образом, маршрут {username} останется, но будет отображать пользовательский контент, определенный администратором.

Изменить:

Если вы не хотите вызывать контроллер вручную, вы можете проанализировать текущие сегменты URL и проверить существующего пользователя, прежде чем определять свой маршрут. Чтобы не усложнять ваш файл routes.php, я бы добавил специальный класс обслуживания, который анализирует ваши сегменты URL:

App\Services\RouteService.php:

<?php

namespace App\Services;

class RouteService {

    public static function isUserRoute()
    {
        if(count(Request::segments()) == 1)
            return !! User::whereUsername(Request::segment(1))->first();
        }

        return false;
    }

}

routes.php:

<?php

use App\Services\RouteService;

if(RouteService::isUserRoute())
{
    get('{username}', 'ProfileController@view');
}

get('{uri}', 'PageController@view')->where('uri', '.+');

Я не проверял это, но это должно работать. Настройте класс RouteService в соответствии с вашими потребностями.

Я использую первый подход в своей CMS, и он работает очень хорошо. Единственная разница в том, что я написал Job, который обрабатывает все входящие запросы и соответственно вызывает действия контроллера.

person tommy    schedule 18.09.2015
comment
Я думаю, что это не лучшая идея, чтобы вызвать контроллер из другого контроллера, как это. Это не очень гибко, я хотел бы иметь возможность настраивать свои маршруты в любое время. Я думаю, что было бы идеально, если бы маршрут не был сопоставлен, если действие контроллера возвращает null или что-то в этом роде. - person Robo Robok; 18.09.2015
comment
Я отредактировал свой ответ. Надеюсь, это хорошее решение для вас. - person tommy; 18.09.2015
comment
Это решение также проблематично. Используя его, я не могу получить данные о маршруте, находясь на другом маршруте. Я пропустил это в своем примере, но я называю свои маршруты по именам, потому что это самый гибкий способ. Используя этот оператор if, мой именованный маршрут не будет определен, когда я буду где-то еще. - person Robo Robok; 19.09.2015
comment
Для этого вам действительно нужно специальное задание обработчика маршрутов, где вы вызываете свои контроллеры вручную, как в моем первом решении. Я думаю, что вы все еще будете очень гибкими, если ваш обработчик маршрута хорошо спроектирован. Другим решением было бы переименовать маршрут вашего профиля, чтобы он соответствовал example.com/@username, возможно, это вариант для вас. В конце концов, я не могу придумать другого решения. - person tommy; 19.09.2015