Laravel-Using (: есть?) подстановочный знак для всех маршрутов?


У меня возникли некоторые проблемы с маршрутизацией.

Я работаю над CMS, и мне нужны два основных маршрута. /admin и /(:any). Контроллер admin используется для маршрута /admin, а контроллер view должен использоваться для чего-либо еще, кроме /admin. С помощью контроллера view я проанализирую url-адрес и покажу правильное содержимое.

Вот что у меня есть:

Route::get(array('admin', 'admin/dashboard'), array('as' => 'admin', 'uses' =>'admin.dashboard@index'));
Route::any('(:any)', 'view@index');

Первый маршрут работает, а второй-нет. я немного поиграл с ним, и кажется, что он работает. если я использую (:any) без вопросительного знака, это работает только тогда, когда я ставлю что-то после /. Если я действительно поставлю там знак вопроса, это вообще не сработает.

Я хочу, чтобы все следующие маршруты шли в view@index:

/
/something
/something/something
/something/something/something
/something/something/something/something
...etc...

Возможно ли это без жесткого кодирования связки (:any?)/(:any?)/(:any?)/(:any?) (которая, как я даже не знаю, работает)?

Как лучше всего это сделать?

7 43

7 ответов:

Edit: после выхода Laravel 4 возникла некоторая путаница в отношении этой темы, этот ответ был нацелен на Laravel 3.

Есть несколько способов приблизиться к этому. Первый метод-это сопоставление (:any)/(:all?):
Route::any('(:any)/(:all?)', function($first, $rest=''){
    $page = $rest ? "{$first}/{$rest}" : $first;
    dd($page);
});

Не лучшее решение, потому что он разбивается на несколько параметров, и по какой-то причине (:all) не работает сам по себе (ошибка?)

Второе решение-использовать регулярное выражение, это лучший способ, чем выше в моем мнение.

Route::any( '(.*)', function( $page ){
    dd($page);
});

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

Event::listen('404', function() {
    $page = URI::current();
    // custom logic, else
    return Response::error('404');
});
Однако мой предпочтительный метод - #2. Надеюсь, это поможет. Что бы вы ни делали, убедитесь, что вы определяете все ваши другие маршруты выше этих поймать все маршруты, любые маршруты, определенные после никогда не будет срабатывать.

Laravel 5

Это решение прекрасно работает на Laravel 5:

Route::get('/admin', function () {

  // url /admin

});

Route::get('/{any}', function ($any) {

  // any other url, subfolders also

})->where('any', '.*');

Люмен 5

Это для Люмена вместо:

$app->get('/admin', function () use ($app) {
  //
});

$app->get('/{any:.*}', function ($any) use ($app) {
  //
});

Попадание в статус 404 кажется мне немного неправильным. Это может привести вас ко всем видам проблем при регистрации 404-х. Я недавно столкнулся с той же проблемой маршрутизации подстановочных знаков в Laravel 4 и решил ее следующим фрагментом:

Route::any('{slug}', function($slug)
{
    //do whatever you want with the slug
})->where('slug', '([A-z\d-\/_.]+)?');
Это должно решить вашу проблему контролируемым образом. Регулярное выражение можно упростить до:
'(.*)?'
Но вы должны использовать это на свой страх и риск.

Правка (добавление):

Поскольку это перезаписывает множество маршрутов, вы следует рассмотреть возможность обертывания его в оператор "App:: before":

    App::before(function($request) {
            //put your routes here
    });

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

Route::get("{path}", "SomeController@serve")->where('path', '.+');

Приведенный выше код захватит рекурсивные суб-URL, которые вы упомянули:

/
/something
/something/something
/something/something/something
/something/something/something/something

Любые другие особые случаи, такие как admin/*, вы можете захватить до этого.

Добавьте это в конец файла маршрутов

App::missing(function($exception)
{
    return View::make('notfound');
});

Из http://scotch.io/tutorials/simple-and-easy-laravel-routing

Спасибо за решение, Уильям. Однако методы 1 и 2 больше не работают Laravel 4, и для того, чтобы использовать решение № 3 в Laravel 4, вам придется запустить событие 404 в вашем start/global.PHP-файл.

App::error(function(Exception $exception, $code)
{
    // i.o. -> this is our catchall!
    // http://stackoverflow.com/questions/13297278/laravel-using-any-wildcard-for-all-routes
    Event::fire('404');

    return View::make('error')->with('exception', $exception)->with('code', $code);

    Log::error($exception);
});
Теперь мы можем справиться с этим в наших маршрутах.php файл:
Event::listen('404', function() {
    // url?
    $url = Request::path();

    // LOGIC HERE

    // else
    return View::make('error');
});

Имея основные леса люмена. В моем случае у меня есть 2 frontend приложения и API routes

<?php // routes/web.php
/** @var \Laravel\Lumen\Routing\Router $router */

$router->group([
    'prefix' => '/api/v1',
    'namespace' => 'App\Http\Controllers'
], function () use ($router) {

    require 'routes-group1.php';
    require 'routes-group2.php';
    // ...
});

$router->get('/admin{any:.*}', function () {
    return file_get_contents('../public/a/index.html');
});

$router->get('{any:.*}', function () {
    return file_get_contents('../public/m/index.html');
});