I'm doing a simple project. I want it to be as minimal as possible so I tried to create system where I can create pages and they're placed at localhost/{page?}
But, here's the problem. I also want some routes to be defined (e.g. route /blog) like below.
Route::get('/{page?}', ['as' => 'root', 'uses' => 'SiteController#getRoot']);
Route::get('blog/{slug?}', ['as' => 'blog.post', 'uses' => 'BlogController#getPost']);
Route::get('blog/page/{page}', ['as' => 'blog.page', 'uses' => 'BlogController#getPage'])->where('page', '[0-9]+');
With this setup, it only uses the first route.
My question is. Is there a way to do this? Or, is this beyond capabilities of Laravel?
Thank you for any help.
Yeah, place your first route as the last route. That way it will get picked up last. You may also need to place the blog/{slug?} before that one as well so blog/slug/{page} is first.
Route::get('blog/page/{page}', ['as' => 'blog.page', 'uses' => 'BlogController#getPage'])->where('page', '[0-9]+');
Route::get('blog/{slug?}', ['as' => 'blog.post', 'uses' => 'BlogController#getPost']);
Route::get('/{page?}', ['as' => 'root', 'uses' => 'SiteController#getRoot']);
Basically what happens is the most basic route is picking up the other routes because there is no reason for it not to and it technically matches the route even though it's not the route you want. Putting the most specific routes first usually handles this issue.
Try reordering them:
Route::get('blog/page/{page}', ['as' => 'blog.page', 'uses' => 'BlogController#getPage'])->where('page', '[0-9]+');
Route::get('blog/{slug?}', ['as' => 'blog.post', 'uses' => 'BlogController#getPost']);
Route::get('/{page?}', ['as' => 'root', 'uses' => 'SiteController#getRoot']);
otherwise they get "overwritten"
Related
It is a very strange situation. Some of my routes doesn't want to be translated. I am using the Laravel mcamara/laravel-localization package.
The routes are translated as described in the documentation.
On my website I have a flag for each translation to change the language. By hover on the flags, it changes only the language, but does not translate the route. The strange thing, is that for some routes it works, but for some not and I cannot find out what is the logic.
For example I have one controller for displaying articles. Here are the routes:
Route::get(LaravelLocalization::transRoute('routes.artciles').'/{id}/{slug}.html', ['as' => 'strategy.show', 'uses' => 'ArticlesController#show']);
Route::get(LaravelLocalization::transRoute('routes.artciles').'/{category}.html', ['as' => 'strategy.category', 'uses' => 'ArticlesController#category']);
Route::get(LaravelLocalization::transRoute('routes.artciles').'.html', ['as' => 'strategy.index', 'uses' => 'ArticlesController#index']);
Here it fails to translate the routes?
By hovering I see just:
en/articles.html, de/articles.html instead of en/articles.html de/artikel.html.
I have found the solution. Here it is for somebody who has similar problem:
in Http/routes.php the code must be without the parameters:
Route::get(LaravelLocalization::transRoute('routes.article'), ['as' => 'strategy.show', 'uses' => 'ArticlesController#show'])->where(['id' => '[0-9]+']);
Route::get(LaravelLocalization::transRoute('routes.article_cat'), ['as' => 'strategy.category', 'uses' => 'ArticlesController#category']);
Route::get(LaravelLocalization::transRoute('routes.articles'), ['as' => 'strategy.index', 'uses' => 'ArticlesController#index']);
And in the lang/routes.php you can include the parameters like this:
'articles' => 'help.html',
'article' => 'help/{id}/{slug}.html',
'article_cat' => 'help/{category}.html',
I'm trying to define routes to access to some views, but it doesn't work :/
Route::group(['prefix' => 'messages'], function () {
Route::get('/', ['as' => 'messages', 'uses' => 'MessagesController#index']);
Route::get('create', ['as' => 'messages.create', 'uses' => 'MessagesController#create']);
Route::post('/', ['as' => 'messages.store', 'uses' => 'MessagesController#store']);
Route::get('{id}', ['as' => 'messages.show', 'uses' => 'MessagesController#show']);
Route::put('{id}', ['as' => 'messages.update', 'uses' => 'MessagesController#update']);
});
I'm always redirected to the home view ('/') of my project when I'm logged.
If I try to access as guest for example : http://myproject.dev/messages I receive a 404 error !
The package that I try to put in my project is : https://github.com/cmgmyr/laravel-messenger
I've installed it on a fresh installation of laravel 5.1 and it's work, but on my project it doesn't work !
My project is in local with MAMP PRO.
With the command php artisan route:list, I can see that routes exists !
EDIT : My routes for authentification was bad !
Route::controller('/','Auth\AuthController') is not a good solution !
To use the MessagesController the user must be authenticated. That means that the user must be logged. The idea is that if a user is not logged he must be redirect to the login page. To make this you must add the auth middleware to the Route::group. The auth middleware will detect if the user is logged and if is not logged it will be redirect to the login page.
Route::group(['middleware' => 'auth', 'as' => 'messages.', 'prefix' => 'messages'], function () {
Route::get('', ['as' => 'index', 'uses' => 'MessagesController#index']);
Route::get('create', ['as' => 'create', 'uses' => 'MessagesController#create']);
Route::post('', ['as' => 'store', 'uses' => 'MessagesController#store']);
Route::get('{id}', ['as' => 'show', 'uses' => 'MessagesController#show']);
Route::put('{id}', ['as' => 'update', 'uses' => 'MessagesController#update']);
});
I think that is this the error
I still can't comment, so I'll write an answer.
I never was able to put a 'root' route inside a Route's group. Laravel need's something there, you can't use "/" or "".
Seeing your code, I suggest you to use a resource view.
Route::resource('messages', 'MessagesController');
It will generate all your routes. I hope it helps.
Consider the following:
Route::get('/', ['as' => 'home.index', 'uses' => 'HomeController#index']);
Route::group(['domain' => 'thechildandthepoet' . env('CONNECTION')], function() {
Route::get('/', ['as' => 'thechildandthepoet.home', 'uses' => 'GameController#index']);
});
When I go to thechildandthepoet.example.local It shows me the contents of
Route::get('/', ['as' => 'home.index', 'uses' => 'HomeController#index']);
completely by passing the fact that I told it which controller to use.
The link looks like: <li>The Child And The Poet</li>
any idea why this doesn't work?
Laravel's router executes the first route that matches given URL.
You don't specify the domain for your first route, therefore it matches all domains. The second route, even though it matches the URL as well, is ignored.
Reorganize your routes.php file, put the routes that specify the domain at the beginning and keep the most generic routes at the end.
Let's say I have 2 urls:
localhost/backend/admin
localhost/backend/admin/users
In my routes.php, I would have a route that looks like this:
Route::group(array('prefix' => 'backend', 'before' => 'auth'), function(){
// Some methods I have on this controller are: getIndex, postUpdate, etc...
Route::controller('admin', 'AppBackend\Controllers\Admin\AdminController');
// Some methods I have on this controller are: getIndex, postUpdate, etc...
Route::controller('admin/users', 'AppBackend\Controllers\Admin\Users\UsersController');
});
The problem is that when I enter admin/users into the browser, Laravel thinks that I'm trying to call a method on the AdminController and finds it doesn't exist among the methods I have for this controller. It seems it would be more ideal, if a method is not found, for Laravel to continue down the routes file and hit my admin/users route and call UsersController.
2 Possible solution that I'm not fully satisfied with:
Reverse the order of the routes. This won't read as naturally as I would like it to, from top to bottom. Plus, I don't know how this solution will hold up over time with every case I have in the future.
Switch to using resource routes. I don't like using PUT/DELETE when it's not supported by some browsers. I like having my own set of action words (and simply renaming and adding to the default resources is not enough or becomes clunky). See also What is the value of using PUT/DELETE with Laravel?
Are there any other good solutions?
The best way of doing routes until now is to make them all manually one by one. In this article Phil Sturgeon pushed me to start to do that and I finally realized that I was having too much trouble using resourceful and restful for a little gain.
It's better to have control of your route listing. Resourceful controllers add too much info, like route parameters, and, to make resourceful controllers not create a bunch of routes I don't use I have to filter what should be generated. In the end it was simply easier to create one route every time I was creating a functionality on my application.
As far as I can tell, to process all your routes in the correct order, Laravel builds a list of your routes, exactly the same way if we were doing it manually. So, there is no performance penalty in doing them manually.
This is an example of my routes in an application I'm just starting:
// Firewall Blacklisted IPs blocked from all routes
Route::group(['before' => 'fw-block-bl'], function()
{
Route::group(['namespace' => 'Application\Controllers'], function()
{
// Pretty error message goes to this route
Route::get('error', ['as' => 'error', 'uses' => 'Error#show']);
Route::get('coming/soon', ['as' => 'coming.soon', 'uses' => 'ComingSoon#index']);
Route::post('coming/soon', ['as' => 'coming.soon.post', 'uses' => 'ComingSoon#register']);
Route::get('coming/soon/register', ['as' => 'coming.soon.register', 'uses' => 'ComingSoon#register']);
Route::post('coming/soon/audit', ['as' => 'coming.soon.audit', 'uses' => 'ComingSoon#audit']);
Route::get('coming/soon/activate/{code}', ['as' => 'coming.soon.activate', 'uses' => 'ComingSoon#activate']);
// Whitelisted on firewall will have access to those routes,
// otherwise will be redirected to the coming/soon page
Route::group(['before' => 'fw-allow-wl'], function()
{
Route::get('user/activate/{code}', ['as' => 'user/activate', 'uses' => 'User#activate']);
Route::get('user/activation/send/{email?}', ['as' => 'user/activation', 'uses' => 'User#sendActivation']);
Route::get('login', ['as' => 'login', 'uses' => 'Logon#loginForm']);
Route::post('login', ['as' => 'login', 'uses' => 'Logon#doLogin']);
Route::get('logout', ['as' => 'logout', 'uses' => 'Logon#doLogout']);
Route::get('register', ['as' => 'register', 'uses' => 'Register#registerForm']);
Route::get('user/recoverPassword/{code}', ['as' => 'user/recoverPassword', 'uses' => 'User#recoverPassword']);
Route::post('user/changePassword', ['as' => 'user/changePassword', 'uses' => 'User#changePassword']);
// Must be authenticated
Route::group(['before' => 'auth'], function()
{
Route::get('/', ['as' => 'home', 'uses' => 'Home#index']);
Route::get('profile', ['as' => 'profile', 'uses' => 'User#profile']);
Route::group(['prefix' => 'offices'], function()
{
Route::get('/', ['uses' => 'Offices#index']);
Route::get('create', ['uses' => 'Offices#create']);
});
Route::group(['prefix' => 'users'], function()
{
Route::get('/', ['uses' => 'Users#index']);
Route::get('create', ['uses' => 'Users#create']);
});
});
});
});
});
All controllers will be namespaced in Application\Controllers and all methods (or subroutes) are prefixed.
EDIT
I'm starting to think I dont name my routes too, I'm not really using them, but I'm still not certain of this, so routes names are not really clear in this raw example. Some also have a 'uses' that could be removed and they will as soon as I decide myself by using names or not.
EDIT 2
I don't do ->before() in routes, because I like to read my routes files sometimes and this method may only be visible after a big list of routes.
When defining a route in Laravel 4 is it possible to define multiple URI paths within the same route?
presently i do the following:
Route::get('/', 'DashboardController#index');
Route::get('/dashboard', array('as' => 'dashboard', 'uses' => 'v1\DashboardController#index'));
but this defeats my purpose, i would like to do something like
Route::get('/, /dashboard', array('as' => 'dashboard', 'uses' => 'DashboardController#index'));
I believe you need to use an optional parameter with a regular expression:
Route::get('/{name}', array(
'as' => 'dashboard',
'uses' => 'DashboardController#index')
)->where('name', '(dashboard)?');
* Assuming you want to route to the same controller which is not entirely clear from the question.
* The current accepted answer matches everything not just / OR /dashboard.
I find it interesting for curiosity sake to attempt to solve this question posted by #Alex as a comment under #graemec's answer to post a solution that works:
Route::get('/{name}', [
'as' => 'dashboard',
'uses' => 'DashboardController#index'
]
)->where('name', 'home|dashboard|'); //add as many as possible separated by |
Because the second argument of where() expects regular expressions so we can assign it to match exactly any of those separated by | so my initial thought of proposing a whereIn() into Laravel route is resolved by this solution.
PS:This example is tested on Laravel 5.4.30
Hope someone finds it useful
If I understand your question right I'd say:
Use Route Prefixing: http://laravel.com/docs/routing#route-prefixing
Or (Optional) Route Parameters: http://laravel.com/docs/routing#route-parameters
So for example:
Route::group(array('prefix' => '/'), function() { Route::get('dashboard', 'DashboardController#index'); });
OR
Route::get('/{dashboard?}', array('as' => 'dashboard', 'uses' => 'DashboardController#index'));