Laravel 4 routing: Cannot use variable name more than once - laravel

I'm having an issue with Laravel 4 routing. I am trying to create two sets of routes:
domain.com/meetings/aa, al-anon, etc.
domain.com/meetings/day/sun, mon, tue, etc.
Here is what I am specifying in my routes file:
Route::resource('meetings/day/{dayName}', 'Meetings_DayController');
Route::resource('meetings/{fellowshipName}', 'Meetings_MeetingController');
I need to be able to pass variables to my resourceful controllers. But I am getting this kind of an error, no matter what order I put the routes in:
Route pattern "/meetings/fellowship/{fellowshipName}/{{fellowshipName}}" cannot
reference variable name "fellowshipName" more than once.
Not only that, but those two routes cause other, undeclared routes to give the same error. My 404 route doesn't kick in for some reason. Ideas, anyone? I've tried everything I can think of. If I could match a three-letter string with the day controller route, that would work, but I can't figure out the regex for a three-letter string in Laravel. \w{3} doesn't work.

You are using Route::resource incorrectly. You can't (and should not) pass a variable to a resource controller. Instead You will need to declare a new route with the verb you need and the parameter. Route::resource only creates several pre-handled routes for you for quick CRUD RESTful access
See the answer to similar situation here: https://stackoverflow.com/a/19608572/385402

Related

Laravel - How do I navigate to a url with a parameter to left of subdirectory

I have to test this Route, but I am not sure how to navigate to it.
Route::get('/{type}/Foo/{page}/{date}', 'FooController#index');
I understand that URLs usually have subdirectories defined before the parameters in the URL.
I have worked with URLs like this example
Route::get('/Foo/{type}', 'FooController#index');
which would have an endpoint that looks like
/Foo?type=bar
Does anybody know how to test a route such as the one above?
Well i think that you need to clear out a bit the difference between route and query parameters.
In your case you are trying to use route parameters which will actually look something like:
/{type}/Foo/{page}/{date} => /myType/Foo/15/12-11-2021
Laravel considers the words inside {} as variables that you can retrieve via request so you can do something like:
$request->type
and laravel will return you the string myType as output.
In your second case that you have tried in the past you are referring to query parameters which are also a part of the $request. Consider it as the "body" of a GET request but i don't mean in any way to convert your post routes to GET :)
The thing with your second url is that:
/Foo/{type} is not similar to /Foo?type=bar
instead it should be like: /Foo/bar
In general query parameters are when you want to send an optional field most of the times in your GET endpoint (for filtering, pagination etc etc) and the route parameters are for mandatory fields that lead to sub-directories for example /Foo/{FooId}/Bar/{BarId}
The thing to remember is that you must be careful about your routes because variables can conflict with other routes.
For example a route looking like this:
Route::get('/foo/{fooId}', [FooController::class, 'getFoo']);
Route::get('/foo/bar', [BarController::class, 'getBar']);
will conflict because laravel will consider bar as the variable of the fooId so your second route can never be accessed.
The solution to this is to order your routes properly like:
Route::get('/foo/bar', [BarController::class, 'getBar']);
Route::get('/foo/{fooId}', [FooController::class, 'getFoo']);
So when you give as a route parameter anything else than bar your will go to your second route and have it working as expected.

Laravel 8 route order from bottom to top

I have installed Laravel 8 and work perfectly, and then i tried to learn about routing and try to make some routes like this
Route::view('testing', 'welcome')->name('testingWelcome');
Route::get('testing',[TestingController::class, 'noParameter'])->name('testingNoParam');
Route::view('testing', 'dashboard')->name('testingDashboard');
Some post in here said that routes in web.php work from top to bottom. But, thats not what i get when i called in url http://localhost/laraps/public/testing. it always called the bottom one. i tried to change the order, but still the last one always get called.
Any explanation for this one? or am i made any wrong configuration?
thanks for any help
A short explanation for this would be that each call to Route::{verb} creates a new route entry under your route collection (relevant code). {verb} ban be any HTTP verb e.g. get, or post etc. This entry is created under an array entry [{verb}][domain/url].
This means that when a new route is registered that matches the same URL with the same method it will overwrite the old one.
So in the case
Route::view('testing', 'welcome')->name('testingWelcome');
Route::get('testing',[TestingController::class, 'noParameter'])->name('testingNoParam');
Route::view('testing', 'dashboard')->name('testingDashboard');
Only the 3rd declaration actually "sticks". There are cases where multiple route definitions can match the same URL for example assume you have these routes:
Route::view('testing', 'welcome')->name('testingWelcome');
Route::get('testing/{optionalParameter?}',[TestingController::class, 'parameter'])->name('testingNoParam');
Route::view('testing/{otherParameter?}', 'dashboard')->name('testingDashboard');
In this case all 3 routes are added to the route collection, however when accessing URL example.com/testing the first matched route will be the one that will be called in this case the welcome view. This is because since all 3 routes are declared, once the router finds one matching route, it stops looking for more matches.
Note: There's generally no point in declaring multiple routes with the exact same URL so this is mainly an academic exercise. However there is often a use case for cases like e.g. model/{id} and model/list` to differentiate between getting info for a specific model and getting a list of models. In this case it's important to declare the routes as:
Route::get('model/list', [ ModelController::class, 'list' ]);
Route::get('model/{id}', [ ModelController::class, 'view' ]);
However you can be more explicit in route declarations using:
Route::get('model/{id}', [ ModelController::class, 'view' ])->where('id',
'\d+');
Route::get('model/list', [ ModelController::class, 'list' ]);
in this case the order does not matter because Laravel knows id can only be a number and therefore will not match model/list

Product And Category Separation In Route (Laravel)

I'm setting up a new route system.
Route::get('/{cat1Url}', 'CategoryController#showCat1')->name('showCat1');
Route::get('/{productUrl}', 'ProductController#showProduct')->name('showProduct');
My sef link is after "/"
But,
{{ route('showProduct',[$p->pr_url]) }}
This method not working with route name. Working only upside route.
I don't want use
"/cat/myVariable"
or
"/product/myVariable"
Can't I use route name to work this way?
What is the solution to this?
In this way, if you make a get request to /something the laravel you start from top of web.php file looking to a route that follows the pattern. Your both routes will follow that pattern, but the laravel will always, pass the first one to controller.
You have two options:
Put only one route, and inside the controller you switch to the appropriate function. But this isn't a great ideia, because this is the function of the Web.php.
Use the routes like the documentation recommend:
Route::get('/cat/{catId}', 'CategoryController#showCat')->name('showCat');
Route::get('/prod/{productId}', 'ProductController#showProduct')->name('showProduct');
and in Controller you make the appropriate handler of your Category or Product.
You will have to have a way to tell Laravel which url to be mapped to what otherwise it will always use the last defined route. So in your case calling /myVariable and /myVariable it will use the latest definition which is showProduct. The only other way is if you use regular expression to differentiate the variables. For example:
Route::get('/{cat1Url}', 'CategoryController#showCat1')
->name('showCat1')->where('cat1Url', 'cat-*');
Route::get('/{productUrl}', 'ProductController#showProduct')
->name('showProduct')->where('productUrl', 'prod-*');
This way your slugs need to start with what you define, but you cannot use just id as a numeric value for both.

Broken route in Laravel depending on where it's defined in the file

I have those routes defined in my routes/web.php :
Route::get('references/', 'referenceController#index')
Route::get('references/{reference}', 'referenceController#show')
Route::get('references/create', 'referenceController#create')
Like that, the references/create route goes to a 404 page.
If I put this route one line before, everything works fine :
Route::get('references/', 'referenceController#index')
Route::get('references/create', 'referenceController#create')
Route::get('references/{reference}', 'referenceController#show')
Then it is obviously because of the {reference} part in my route, right? But as I wanted to filter the reference perfectly, I've put a pattern in RouteServiceProvider.php. This pattern should check that my reference is a well-formed UUID :
Route::pattern('reference', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{10}');
Miles away from the word "create", which doesn't match the pattern.
Do you know why my route is going to a 404 page depending on its position in the file?
This is how Laravel is supposed to work. It isn't very clear in the documentation though I'll admit.
Supplementing Resource Controllers
If you need to add additional
routes to a resource controller beyond the default set of resource
routes, you should define those routes before your call to
Route::resource; otherwise, the routes defined by the resource method
may unintentionally take precedence over your supplemental routes:
Route::get('photos/popular', 'PhotoController#method');
Route::resource('photos', 'PhotoController');
This is also true if you are defining non-resource routes as you noted in your example. This is because it will try to pass "create" as the id of the reference parameter in the route which of course is not valid.
Rule of Thumb
When defining routes that have the same number of url segments, always define the route that does not have a parameter variable first. The routes file will go top-down and find the first route that matches the current request.

Redirects to same action from different urls in laravel 5.2

I am using Laravel 5.2.
I am passing parameters via two urls. But it always goes to the first route only.
code in my routes.php is as follows:
Route::get('{department}', 'settings#load_department_settings')->middleware('auth');
Route::get('{id}', 'settings#load_staff')->middleware('auth');
Anchor tags in view is as follows:
<td>{{$staff->name}}</td>
<td>{{$staff->deptname}}</td>
The issue is it always uses 'settings#load_department_settings'. How could i use 'settings#load_staff' when clicking on staff name?
It is always going to use the {department} route because that is matching anything on the root / slash. You need tto dive at least one of them unique prefixes. For example:
Route::get('department/{department}', 'settings#load_department_settings')->middleware('auth');
Route::get('staff/{id}', 'settings#load_staff')->middleware('auth');
Then
<td>{{$staff->name}}</td>
<td>{{$staff->deptname}}</td>

Resources