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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13297278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 05:07:41  来源:igfitidea点击:

Laravel - Using (:any?) wildcard for ALL routes?

phplaravelroutingwildcardlaravel-3

提问by qwerty

I am having a bit of trouble with the routing.

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

I'm working on a CMS, and i need two primary routes. /adminand /(:any). The admincontroller is used for the route /admin, and the viewcontroller should be used for anything else than /admin. From the viewcontroller, i will then parse the url and show the correct content.

我正在研究 CMS,我需要两条主要路线。/admin/(:any)。该admin控制器用于路由/adminview控制应该用于任何东西比其他/admin。从view控制器中,我将解析 url 并显示正确的内容。

This is what i have:

这就是我所拥有的:

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

The first route works, but the second one doesn't. I played around with it a little bit, and it seems if i use (:any)without the question mark, it only works if i put something after /. If i doput the question mark there, it doesn't work at all.

第一条路线有效,但第二条路线无效。我玩了一会儿,似乎如果我(:any)不带问号使用,它只有在我在/. 如果我确实把问号放在那里,它根本不起作用。

I want all of the following routes to go to view@index:

我希望以下所有路线都转到 view@index:

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

Is this possible without hardcoding a bunch of (:any?)/(:any?)/(:any?)/(:any?)(which i don't even know works)?

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

What's the best way to go about this?

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

采纳答案by William Cahill-Manley

Edit: There has been some confusion since the release of Laravel 4 regarding this topic, this answer was targeting Laravel 3.

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

There are a few ways to approach this.

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

The first method is matching (:any)/(:all?):

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

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

Not the best solution because it gets broken into multiple parameters, and for some reason (:all) doesn't work by itself (bug?)

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

The second solution is to use a regular expression, this is a better way then above in my opinion.

第二种解决方案是使用正则表达式,在我看来,这是一种比上面更好的方法。

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

There is one more method, which would let you check if there are cms pages even when the route may have matched other patterns, provided those routes returned a 404. This method modifies the event listener defined in routes.php:

还有一种方法,即使路由可能与其他模式匹配,也可以让您检查是否有 cms 页面,前提是这些路由返回 404。此方法修改在 中定义的事件侦听器routes.php

Event::listen('404', function() {
    $page = URI::current();
    // custom logic, else
    return Response::error('404');
});

However, my preferred method is #2. I hope this helps. Whatever you do, make sure you define all your other routes above these catch all routes, any routes defined after will never trigger.

但是,我的首选方法是#2。我希望这有帮助。无论您做什么,请确保您在上面定义了所有其他路由,这些路由可以捕获所有路由,之后定义的任何路由都不会触发。

回答by Andrea

Laravel 5

Laravel 5

This solution works fine on Laravel 5:

此解决方案在 Laravel 5 上运行良好:

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

  // url /admin

});

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

  // any other url, subfolders also

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


Lumen 5

流明 5

This is for Lumen instead:

这是针对 Lumen 的:

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

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

回答by Eelke van den Bos

Hitting a 404 status seems a bit wrong to me. This can get you in all kind of problems when logging the 404's. I recently bumped into the same wildcard routing problem in Laravel 4 and solved it with the following snippet:

达到 404 状态对我来说似乎有点错误。这会让您在记录 404 时遇到各种问题。我最近在 Laravel 4 中遇到了相同的通配符路由问题,并使用以下代码段解决了它:

Route::any('{slug}', function($slug)
{
    //do whatever you want with the slug
})->where('slug', '([A-z\d-\/_.]+)?');

This should solve your problem in a controlled way. The regular expression can be simplified to:

这应该以可控的方式解决您的问题。正则表达式可以简化为:

'(.*)?'

But you should use this at your own risk.

但是您应该自担风险使用它。

Edit (addition):

编辑(补充):

As this overwrites a lot of routes, you should consider wrapping it in an "App::before" statement:

由于这会覆盖很多路由,因此您应该考虑将其包装在“App::before”语句中:

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

This way, it will not overwrite custom routes you define later on.

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

回答by Guy

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

The above code will capture the recursive sub urls you mentioned:

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

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

Any other special cases, such as admin/*, you can capture before this one.

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

回答by Luke

Just spelling-out my experience in case it helps someone piece something together.

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

I built a self-API-consuming React app on Laravel. It has a single view served by Laravel/Lumen. It uses the React router. Clicking links in the app always worked, but typing-in URLs needed the following consideration:

我在 Laravel 上构建了一个自用 API 的 React 应用程序。它有一个由 Laravel/Lumen 服务的单一视图。它使用 React 路由器。 单击应用程序中的链接始终有效,但输入 URL 需要考虑以下因素:

In Laravel I used the following in my web.php routes file:

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

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

And everything worked.

一切都奏效了。

Then I switched the project to Lumen. Thanks to this post, I used the following in my web.php routes file:

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

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

This worked for first level URLS such as:

这适用于第一级 URL,例如:

/
/something 

However,

然而,

/something/something etc.

did not.

没有。

I looked in the network tab in Google Developer tools and noticed that the URL for app.js was appending /somethingin front of app.js on second and higher tier URLS, such as:

我查看了 Google 开发人员工具中的网络选项卡,注意到 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)

All I had to do was add a leading slash to my app.js source in my single view page such as:

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

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

Instead of:

代替:

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

so:

所以:

This worked in Laravel(It was a Blade file that may have automatically resolved the js/app.js URL)

这在Laravel有效(这是一个 Blade 文件,可能会自动解析 js/app.js URL)

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

with

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

But, I had to do this in Lumen(Not a Blade file):

但是,我必须在Lumen (不是 Blade 文件)中执行此操作

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

with

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

回答by Edmhs

Add this in the end of routes file

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

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

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

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

回答by Chris Schalenborgh

Thanks for the solution William. However methods 1 & 2 aren't working anymore Laravel 4, and in order to use solution #3 in Laravel 4 you will have to fire the 404 event in your start/global.php file.

感谢威廉的解决方案。然而,方法 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);
});

Now we can handle this in our routes.php file:

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

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

    // LOGIC HERE

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

回答by Andrew Luca

Having basic lumen scaffolding. In my case, I have 2 frontend apps and api routes

有基本的流明脚手架。就我而言,我有 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');
});