Laravel - 为所有路由使用(:任何?)通配符?

时间:2012-11-08 20:29:32

标签: php laravel routing wildcard laravel-3

我在路由方面遇到了一些麻烦。

我正在使用CMS,我需要两条主要路线。 /admin/(:any)admin控制器用于路由/adminview控制器应用于除/admin以外的任何其他控制器。从view控制器,我将解析网址并显示正确的内容。

这就是我所拥有的:

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

第一条路线有效,但第二条路线没有。我玩了一下它,似乎如果我使用没有问号的(:any),它只有在/之后放一些东西时才有用。如果我将问号放在那里,它根本不起作用。

我希望以下所有路线都能查看@ index:

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

如果没有硬编码一堆(:any?)/(:any?)/(:any?)/(:any?)(我甚至不知道有效),这可能吗?

最好的方法是什么?

10 个答案:

答案 0 :(得分:74)

Laravel 5

此解决方案适用于Laravel 5:

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

  // url /admin

});

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

  // any other url, subfolders also

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

流明5

这是针对Lumen的:

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

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

答案 1 :(得分:46)

达到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
    });

这样,它不会覆盖您稍后定义的自定义路由。

答案 2 :(得分:24)

编辑:自从Laravel 4发布关于这个话题以来,有一些混乱,这个答案针对的是Laravel 3。

有几种方法可以解决这个问题。

第一种方法是匹配(:any)/(:all?)

Route::any('(:any)/(:all?)', function($first, $rest=''){
    $page = $rest ? "{$first}/{$rest}" : $first;
    dd($page);
});

不是最好的解决方案,因为它被分解成多个参数,并且由于某种原因(:all)本身不起作用(bug?)

第二个解决方案是使用正则表达式,这是我认为更好的方法。

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。我希望这有帮助。无论你做什么,一定要确定你所有其他路线都定义在这些路线之上,所有路线都是永久不会触发的。

答案 3 :(得分:6)

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

上面的代码将捕获您提到的递归子网址:

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

任何其他特殊情况,例如admin / *,您可以在此之前捕获。

答案 4 :(得分:5)

在路线文件

的末尾添加此项
App::missing(function($exception)
{
    return View::make('notfound');
});

来自http://scotch.io/tutorials/simple-and-easy-laravel-routing

答案 5 :(得分:2)

感谢William解决方案。然而方法1& 2不再使用Laravel 4,并且为了在Laravel 4中使用解决方案#3,您必须在start / global.php文件中触发404事件。

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);
});

现在我们可以在routes.php文件中处理这个:

Event::listen('404', function() {
    // url?
    $url = Request::path();

    // LOGIC HERE

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

答案 6 :(得分:1)

有基本的管腔脚手架。在我的情况下,我有2个前端应用程序和api路由

<?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');
});

答案 7 :(得分:0)

只是说出我的经验,以防有人拼凑东西。

我在Laravel上构建了一个自API消耗的React应用。 它具有Laravel / Lumen提供的单一视图。 它使用React路由器。 在应用程序中单击链接始终有效,但是输入URL需要以下注意事项:

在Laravel中,我在web.php路由文件中使用了以下内容:

Route::view('/{path?}', 'app')
    ->where('path', '.*')
    ->name('react');

一切正常。

然后,我将项目切换到流明。 感谢这篇文章,我在web.php路由文件中使用了以下内容:

$router->get('/{all:.*}', function() {
    return view('app');
});

这适用于一级URL,例如:

/
/something 

但是,

/something/something etc.

没有。

我在Google Developer工具的“网络”标签中查看,发现app.js的URL在第二层和更高层URLS的app.js前面附加了 / something 。 / p>

myapp.com/something
app.js URL:  myapp.com/js/app.js  (as it should be)

myapp.com/something/something
app.js URL:  myapp.com/something/js/app.js  (not found)

我要做的就是在单视图页面的app.js源代码中添加一个斜杠,例如:

<script src="/js/app.js" defer></script>

代替:

<script src="js/app.js" defer></script>

如此:

这在 Laravel (这是一个Blade文件,可能已自动解析js / app.js URL)中起作用了

<script src="{{ asset('js/app.js') }}" defer></script>

使用

Route::view('/{path?}', 'app')
    ->where('path', '.*')
    ->name('react');

但是,我必须在流明 (不是Blade文件)中完成此操作:

<script src="/js/app.js" defer></script>

使用

$router->get('/{all:.*}', function() {
    return view('app');
});

答案 8 :(得分:0)

从Laravel 5.5开始的故障转移路线

使用Route::fallback方法,您可以定义一个路由,当没有其他路由与传入请求匹配时将执行该路由。通常,未处理的请求将通过应用程序的异常处理程序自动呈现“ 404”页面。但是,由于通常会在fallback文件中定义routes/web.php路由,因此web中间件组中的所有中间件都将应用于该路由。您可以根据需要随意向此路由添加其他中间件:

Route::fallback(function () {
    //
});

注意:后备路由应始终是应用程序注册的最后一条路由。

答案 9 :(得分:0)

Laravel 8 / 只在子目录下重定向

我不想重定向所有不存在的 URL,而只想重定向特定子目录中的 URL(例如 https://example.com/subdir/*

如果我只是想重定向所有丢失的 URL,我可以使用 web.php 文件末尾的 fallback route

Route::fallback(function () {
    //
});

但是因为我想只重定向子目录中的网址,所以我使用了这段代码,它对我有用(只是重定向到 /):

Route::get('subdirectory/{any}', function($page){return redirect()->to('/');})->where('any', '.*');

我在 FallbackRouteTest.php 中找到了这个。