Laravel-在所有路由中使用(: : any?)通配符?

路由出了点问题。

我在研究 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?)(我甚至不知道它们是否有效) ,这可能吗?

最好的办法是什么?

130540 次浏览

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

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

第一种方法是匹配 (: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。希望这个能帮上忙。无论你做什么,确保你定义了所有其他的路线,以上这些捕捉所有的路线,任何路线后定义永远不会触发。

谢谢你的解决方案,威廉。然而,方法1和方法2不再适用于 Laravel4,为了在 Laravel4中使用解决方案 # 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);
});

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

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


// LOGIC HERE


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

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

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

将此添加到路由文件的末尾

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

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

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) {
//
});
Route::get("{path}", "SomeController@serve")->where('path', '.+');

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

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

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

有基本的流明脚手架。在我的情况下,我有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');
});

只是把我的经历说出来,以防有人能从中找到线索。

我在 Laravel 上构建了一个自我 API 消耗的 React 应用程序。 它只有一个视角,由 Laravel/Lumen 提供。 它使用反应路由器。 点击应用程序中的链接总是有效的,但是输入 URL 需要考虑以下几点:

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

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

一切都很顺利。

然后我把项目转给了 Lumen。 多亏了这篇文章,我在 web.php 路由文件中使用了以下内容:

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

这适用于第一级 URL,如:

/
/something

但是,

/something/something etc.

没有。

我查看了 Google Developer 工具中的网络选项卡,注意到 app.js 的 URL 在 app.js 前面附加了 什么的到第二层和更高层的 URL,比如:

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

但是,我不得不这样做,在 Lumen (非刀锋档案):

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

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

从 Laravel 5.5开始的撤退路线

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

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

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

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

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

如果我只想使用 重定向所有丢失的 URL,我可以在 web.php 文件的末尾使用 撤退路线:

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

但是当我想要使用 只重定向子目录中的 URL时,我使用了这个代码,它对我很有用(只是重定向到/) :

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

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