69

我的路由有点麻烦。

我正在开发 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?)(我什至不知道有效)?

解决这个问题的最佳方法是什么?

4

10 回答 10

125

拉拉维尔 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) {
  //
});
于 2016-01-02T10:50:39.703 回答
48

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

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

于 2013-03-23T11:29:36.937 回答
30

编辑:自 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。我希望这有帮助。无论您做什么,请确保您在这些路线之上定义所有其他路线,捕获所有路线,之后定义的任何路线都不会触发。

于 2012-11-08T20:49:54.747 回答
10
Route::get("{path}", "SomeController@serve")->where('path', '.+');

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

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

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

于 2016-01-02T18:54:34.753 回答
8

只是拼出我的经验,以防它帮助某人拼凑一些东西。

我在 Laravel 上构建了一个自用 API 的 React 应用程序。它有一个由 Laravel/Lumen 提供的单一视图。它使用 React 路由器。 单击应用程序中的链接始终有效,但输入 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 在第二层和更高层 URL 的 app.js 前面附加了 /something,例如:

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中有效 (它是一个可能自动解析 js/app.js URL 的 Blade 文件)

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

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

但是,我必须在Lumen (Not a Blade 文件)中这样做:

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

$router->get('/{all:.*}', function() {
    return view('app');
});
于 2019-04-27T12:58:19.090 回答
5

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

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

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

于 2014-05-26T11:22:32.783 回答
3

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中找到了这个。

于 2021-06-20T04:42:14.670 回答
2

感谢威廉的解决方案。然而,方法 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');
});
于 2013-03-13T23:43:11.937 回答
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');
});
于 2018-01-17T03:29:26.167 回答
0

自 Laravel 5.5 以来的后备路由

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

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

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

于 2020-12-11T16:59:10.670 回答