问题
I am having a bit of trouble with the routing.
I'm working on a CMS, and i need two primary routes. /admin
and /(:any)
. The admin
controller is used for the route /admin
, and the view
controller should be used for anything else than /admin
. From the view
controller, i will then parse the url and show the correct content.
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 do put the question mark there, it doesn't work at all.
I want all of the following routes to go to 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)?
What's the best way to go about this?
回答1:
Edit: There has been some confusion since the release of Laravel 4 regarding this topic, this answer was targeting Laravel 3.
There are a few ways to approach this.
The first method is matching (: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?)
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
:
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:
Laravel 5
This solution works fine on Laravel 5:
Route::get('/admin', function () {
// url /admin
});
Route::get('/{any}', function ($any) {
// any other url, subfolders also
})->where('any', '.*');
Lumen 5
This is for Lumen instead:
$app->get('/admin', function () use ($app) {
//
});
$app->get('/{any:.*}', function ($any) use ($app) {
//
});
回答3:
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:
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(function($request) {
//put your routes here
});
This way, it will not overwrite custom routes you define later on.
回答4:
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.
回答5:
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
回答6:
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:
In Laravel I used the following in my web.php routes file:
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:
$router->get('/{all:.*}', function() {
return view('app');
});
This worked for first level URLS such as:
/
/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 /something in front of app.js on second and higher tier URLS, such as:
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:
<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)
<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):
<script src="/js/app.js" defer></script>
with
$router->get('/{all:.*}', function() {
return view('app');
});
回答7:
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.
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:
Event::listen('404', function() {
// url?
$url = Request::path();
// LOGIC HERE
// else
return View::make('error');
});
回答8:
Having basic lumen scaffolding. In my case, I have 2 frontend apps and 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');
});
来源:https://stackoverflow.com/questions/13297278/laravel-using-any-wildcard-for-all-routes