I have a homegrown, Laravel 5.1 base application on top of which I build specific applications. The base application uses a named route for login, naturally called "login", which listens for GET /login.
In one of my specific applications, I attempted to overload that route to send the requests to a different controller. It seemed to work for a while, but then it started going to the base application's controller again. I'm sure I changed something to break it, but the problem is that I can't figure out how to fix it again.
My base application routes are all defined in app/Http/Routes/core.php. The relevant route:
Route::get('login', [
'as' => 'login',
'uses' => '\MyVendor\Core\Http\Controllers\AuthController#getLogin'
]);
My specific application routes are defined in app/Http/Routes/app1.php. The relevant route:
Route::get('login', [
'as' => 'login',
'uses' => 'App1\AuthController#getLogin'
]);
App2 and App3 are defined similarly. My app/Http/routes.php adds these routes like this:
require 'Routes/core.php';
Route::group(['domain' => 'app1.com'], function() {
require 'Routes/app1.php';
});
Route::group(['domain' => 'app2.com', function() {
require 'Routes/app2.php';
});
Route::group(['domain' => 'app3.com', function() {
require 'Routes/app3.php';
});
The problem I am seeing is that visiting app1.com/login, app2.com/login, and app3.com/login all result in the execution of \MyVendor\Core\Http\Controllers\AuthController#getLogin rather than App1\AuthController#getLogin.
EDIT: I have changed the problem description since I was describing it incorrectly as a problem with calls to route('login').
The index of the routes in Laravel follows a "$domain$uri" format, therefore routes with a domain won't overwrite those without. A fallback route without a domain should be declared after the domain group, so it is later in the route collection and won't match before a route with a matching domain.
"the most recent definition for a route is the effective route"
This is not a bug, this is the expected behaviour, a simple example would be setting a variable to value 1 then setting it to value 2, of course the (most) recent value takes place.
Related
So building a few pages on the same template and loading the content via AJAX. Most of the content are forms. Views are defined by step number (1,2,3,4,5....32)
Here is how I built my route:
Route::get('onboarding/', [
'as' => 'get-onboarding-start',
'uses' => 'OnboardingController#getStart'
]);
Route::get('onboarding/{i}', [
'as' => 'get-onboarding-step',
'uses' => 'OnboardingController#getNextStep'
]);
Route::post('onboarding/{i}', [
'as' => 'post-onboarding-step',
'uses' => 'OnboardingController#postStepForm'
]);
Now one method in the controller cannot handle all the work. Meaning I will need to redirect to another method based on the $i (step number).
I am afraid that it is not simple to read if I put a big blog of switch case $i = 1,2,3...
At the same time I don't want to write 32 different routes.
What would you propose?
Hard code all the routes meaning: 'onboarding/username' then
'onboarding/email' etc... etc... The good point is that it is super
simple to read in the views and you know exactly what the next step
is... no need to check what the number corresponds to.
Catch all as coded now and redirect to different methods in the controller
Something better, super easy to read and with little lines of
code... which is .... ??
If these steps are going to remain as they are without many changes in the future, I'd go for the first option (having 32 get & 32 post routes). This will keep your application simple, if you'd want to apply parameters or middleware to them you can use route groups. Below I've posted a small code example from the laravel documentation
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
My laravel application has a model - Video. It is the main model so the route was named videos. But after the development I discovered that there is a folder on the production server named videos
So now rewriting the url to include index.php in .htaccess does not work.
I cannot change the name of videos folder which is already present.
I cannot change the db table name either. I don't want to do that, its too much work.
Is there a way to change the route name to something else like lvideos or vvideos?
I tried changing it in routes but it seems there are other places where I have to change it. It throws me an error in the controller.
Can anyone suggest a solution for this?
I don't want to give the link with index.php to the users
Thank you.
You will have to change the route anywhere it is referenced.
In the future if you think a route might change, you could use named routes and then reference the route name anywhere you need to use it.
For example:
Route::group(['prefix' => 'videos'], function() {
Route::get('/', [
'uses' => 'VideosController#index',
'as' => 'videos.index',
]);
Route::get('{id}', [
'uses' => 'VideosController#show',
'as' => 'videos.show',
]);
});
Then everywhere you use these routes you use the name, for example in a view:
Videos
The link will still work even if you change the route to Route::group(['prefix => 'iVideos']); Even though the route changed, the name did not.
I have a site in a subfolder, example.com/mysite. I have a route there, login, which is accessed via example.com/mysite/login. This is the route:
Route::group(array('domain' => 'example.com'), function()
{
Route::get('/', function()
{
return Redirect::to('login');
});
Route::get('/login/', array('as' => 'login', 'uses' => 'AccountController#login'));
})
The problem is, when I have a link in my view like so:
<a href='{{{ route('login') }}}'>Login page</a>
It displays the path example.com/login instead of example.com/mysite/login. It think this has something to do with the domain group, but I don't know how to tell it to keep the current subdirectory. I've tried changing the domain to example.com/mysite in the group command, but that just causes an error. The redirection to login works, but how do I get the correct link in the view?
Turns out, this is because when it generates the route, it uses the domain provided in the group instead of getting it from the url. It can be overriden though, by specifying an empty domain in the individual route match, like so:
Route::get('/login/', array('as' => 'login', 'uses' => 'AccountController#login', 'domain' => ''));
This will allow it to ignore the domain specified in the group function. Unfortunately, from what I can tell, you need to do this for all of them.
Your routes do not follow a relative path. Even if you are in example.com/mysite, your route is made within the example.com domain.
Your redirect redirects you to example.com/login.
This is where your route is. Your redirect is redirecting to 'login'.
You named your route vendor_login. Therefore within the view, you have to write <a href='{{{ route('vendor_login') }}}'> to access your correct route.
Still, going to example.com/mysite/login will not show you your login page. It is available via example.com/login.
If you want to be available via example.com/mysite/login, use the following code.
Route::group(array('domain' => 'example.com'), function()
{
Route::get('/', function()
{
return Redirect::route('vendor_login');
});
Route::group(array('prefix' => 'mysite'), function()
{
Route::get('/login/', array('as' => 'vendor_login', 'uses' => 'AccountController#login'));
});
});
The difference here is that the login route is now placed within a group that uses the 'mysite' prefix. In this case, your login route is available via example.com/mysite/login.
The redirect is changed from Redirect::to('login') (which redirected to example.com/login, to Redirect::route('vendor_login') which redirects to the named route vendor_login, independent of its path.
EDIT:
Routes are absolute. If you want to make a link that is relative to the same depth, in your view just do Login. But this is not recommended. In that case you can not show the same view/link from routes with a different depth. Instead use named routes (as you did) which give you the most flexibility. Just put in your view the correct name vendor_login and change your Redirect::to to Redirect::route('vendor_login')
Hope this helps
I'm trying to understand routing in Laravel 4. I read a good post here on StackOverflow and a link to beware the route to evil, a post about manually specifying routes. I like the idea of specifying my routes manually and having the routes.php act as documentation. But it seems like I need to be cautious about the order of my Routes if I'm going to specify my own instead of using Route::resource() If I have the new or create route before the show then I won't be routed to the show because of the variable in URI? The order in which the routes are defined is important right?
// This will not work if I try and browse to dogs/new
Route::get('dogs', array('as' => 'dogs', 'uses' => 'DogsController#index'));
Route::get('dogs/{dogs}', array('as' => 'dog', 'uses' => 'DogsController#show'));
Route::get('dogs/new', array('as' => 'new_dog', 'uses' => 'DogsController#create'));
It seems I need to make sure that the dogs/new comes before the dogs/{dogs} for new to return correctly. I'm not clear on what {dogs} does or that's different from (:any) or {any} I've seen a few different uses in examples and pseudo code. I see that /new is the same as {...} when the route is before the more specific is the {} like a wildcard in Laravel 4? Is the (:...) the old way?
As an aside I've noticed a different naming convention from some of the examples I've seen when I run php artisan routes with a resource route like Route::resource('photos', 'PhotosController'); The method and named route for post to index to a create a new resource is named photos.store and #store. The method and named route for a link to a form to create a new resource is photos.create and #create. Is that Laravel 4 thing or conventions in other frameworks?
Route::get('dogs/{dogs}', array('as' => 'dog', 'uses' => 'DogsController#show'));
The above url expecting a parameter after dogs segment.
for example: http://laravel.com/dogs/xyz, http://laravel.com/dogs/new
after dogs url segment, Laravel will accept anything. So, your another routing will never executed for the route parameter.
Route::get('dogs/new', array('as' => 'new_dog', 'uses' => 'DogsController#create'));
More about route parameters:
http://laravel.com/docs/routing#route-parameters
Resource Controllers
Laravel and Ruby on rails support resource full routing. I think, Tailor borrow the resource full routing idea from Ruby on rails.
The following routes will generate if you use resource controller:
index
create
store
update
show
edit
destroy
http://guides.rubyonrails.org/routing.html
http://laravel.com/docs/controllers#resource-controllers
I got an annoying problem with a route, for a section of a CMS that I'm developing.
I got routes for all the sections, "products", for example:
Route::get('admin/products', array('as' => 'admin/products', 'uses'=> 'admin.products#index'));
Route::get('admin/products/create', array('as' => 'admin/products/create', 'uses'=> 'admin.products#create'));
Route::get('admin/products/edit/(:num)', array('as' => 'admin/products/edit', 'uses'=> 'admin.products#edit'));
Route::get('admin/products/delete/(:num)', array('as' => 'admin/products/delete', 'uses'=> 'admin.products#delete'));
.. and the related files, like the products controller, the product model and the views.
Everything was doing well until I decided to create a new section, "users". I used the same approach as "products", creating the routes and the other files. In fact I just copied and paste the files, making the changes when needed -- pretty straightforward. By accessing "admin/users" and "admin/users/create", it works as expected. But I can't access "/users/edit/1" and "/users/delete/1". I thought it would be a route problem, but when I tested the route file, I got a 404 even before reaching the route. Here's an example:
Route::get('admin/users/edit/(:num)', function()
{
return "Holy Hell.";
});
"Holy Hell" is never printed into the screen.
Here's the config for "users":
Route::get('admin/users', array('as' => 'admin/users', 'uses'=> 'admin.users#index'));
Route::get('admin/users/edit/(:num)', array('as' => 'admin/users/edit/', 'uses'=> 'admin.users#edit'));
Route::get('admin/users/create', array('as' => 'admin/users/create', 'uses'=> 'admin.users#create'));
Route::get('admin/users/delete/(:num)', array('as' => 'admin/users/delete', 'uses'=> 'admin.users#delete'));
Things that I noticed / Checked:
The index view, where is the users list, got a "URL::to_route('admin/users/edit')" function. I have no errors on the screen, so Laravel understands that the route 'admin/users/edit' is set correctly.
I know that this is not a general problem, because the "edit" and "delete" methods for the other CMS sections have no issues.
The views for these methods are there. So this is not a "file not found" issue.
I wonder if I'm missing something really obvious here. Any ideas? If not, would anyone please tell me how to debug this?
Thank you very much.
EDIT: Heads up
Your routes are in a bad order. Reverse them. Routes are evaluated top down, so anything with admin/products in the route will route to admin.products#index and nothing else.
In your edit method, you need to have the id parameter defined.
Since you didn't post your controller, I'm assuming this is why, since the closure does not have the $id passed to it. Example:
// Required user id:
Route::get('admin/users/edit/(:num)', function($id)
{
return "Holy Hell.";
});
// Optional user id:
Route::get('admin/users/edit/(:num?)', function($id = null)
{
return "Holy Hell.";
});
In your case, you probably don't want the optional part unless you plan on spewing out an error (or redirecting on error).