Removing /profile/ from /profile/{username} keyword from Route Web.php does not work - laravel

I have a Route
Route::get('/{username}', 'ProfileController#profile')->name('profile.view');
If I keep it in the middle of the file, all the route after this does not work.
If I keep this in the bottom, then everything works.
Also, If I add any work like Profile, it works.
Route::get('profile/{username}', 'ProfileController#profile')->name('profile.view');
How to solve this?

That's the way it is supposed to work as you are using a wildcard to match everything. So either you put it at the bottom of the file and it will be used as a fallback route, which means nothing above it should match, then it will fallback to that route. Or you can use a regex to match the username to something which makes it different then the other routes, something like:
Route::get('{username}', 'ProfileController#profile')
->name('profile.view')
->where('username', 'YOUR REGEX HERE');
I would go with the one you showed and already works:
Route::get('profile/{username}', 'ProfileController#profile')
->name('profile.view');
// or
Route::get('user/{username}', 'ProfileController#profile')
->name('profile.view');

Related

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

Best way to pass url as parameter to route

I am trying to pass any full url in as parameter to route, but the slash seems to mess everything up. If a route is passed in encoded, the route seems to decode it, is there a way to stop this or encode the url again at route level?
Route::get('add/{title?}/{url?}', 'HomeController#add')->name('add');
also i have tired
Route::get('add/{title?}/{url?}', 'HomeController#add_')->where('url', '(.*)')->name('add_popup');
but if it comes across question mark in the url it will drop anything after the question mark.
Check this out
Route::get("url/{url}", function($url) {
return $url;
})->where('url', '.*');
Example: http://myapp.test/url/http://try.me.com prints
http://try.me.com
I would recommend Jeunes answer, however if you still want a route parameter you could do a base64 encode/decode. This will not make for a pretty url though.
JS
btoa("http://someurl.test")
PHP
Route::get('url/{url}', function ($url) {
return base64_decode($url);
});

Codeigniter routes don't work correctly

I have two string in routing config.
$route['education/course/(:any)'] = "education/course/$1";
$route['education/course/(:any)/(:num)'] = "education/lection/$1/$2";
But when I went to /education/course/my_course/1, the first rule worked, but the second didn't.
Please help! I'm newbie in CI.
Routes run in the order they are defined. Your second one will never be applied because the (:any) wildcard is capturing, well, anything.
I believe you should be able to switch the order so the most specific is first, followed by the least specific:
$route['education/course/(:any)/(:num)'] = "education/lection/$1/$2";
$route['education/course/(:any)'] = "education/course/$1";
Since both two routes are similar in the first three segments
education / course / (:any)
And since Route.php runs procedural (line by line),
Requesting a page like /education/course/my_course/1 matches the first route pattern (below)
$route['education/course/(:any)'] = "education/course/$1";
And also, requesting a page like /education/course/my_course/1/23 will still matches the first route pattrn, because Route.php only cares if your requested URL link matched the specified route pattern or not, otherwise go check the next route.
So, switching the order of the routes will fix the problem.

Laravel 4 Route Filter Never Called

I am sure that I am doing something wrong that is very obvious, but for some reason I cannot get any filters except App::before to work in my test application.
//routes.php
Route::get('site/login',
array(
'before'=>'science',
'as'=>'site/login',
'uses'=>'HomeController#getLogin',
)
);
Route::controller(site, 'HomeController');
//filters.php
App::before(function($request){
//var_dump("Before"); exit;
});
Route::filter('science',function(){
dd("Science B!TCH!");
exit;
});
//HomeController.php
public function getLogin(){
$this->layout->body = View::make('home.login');
}
The object was first to ensure that a user was not logged in so I was trying to use the built-in "guest" filter, but it was never being called. So I later created the "science" filter to test if ANY routes would work. If I uncomment the var_dump line in App::before, it displays "Before" and exits as expected.
Can anyone see what I am doing wrong here? When I go to the /site/login page I should see my Breaking Bad movie quote instead of the actual page. However, I am seeing my login form as if nothing was happening.
Thanks!
UPDATE:
I changed the route to look like this now:
//routes.php
Route::get('site/login', 'HomeController#getLogin')->before('science');
... and it works. I get the debugging string "SCIENCE ..." on the screen.
It also works if I do the following
//HomeController.php
public function __construct(){
$this->beforeFilter('science');
}
Are there any use cases or conditions in which the array version of routes gets ignored?
UPDATE 2:
In my efforts to simplify my original description I neglected to show other routes that were in routes.php. Take a look below.
//routes.php
Route::get('site/login',
array(
'before'=>'science',
'as'=>'site/login',
'uses'=>'HomeController#getLogin'
)
);
Route::post('site/login',
array(
'as'=>'site/login',
'uses'=>'HomeController#postLogin'
)
);
Having the POST route AFTER the GET route is what is causing the problem. When I put the POST route BEFORE the GET route, the GET route works with the filter as expected.
Now, I was under the impression that Laravel treated GET and POST requests differently, hence the usage of the different static methods in Route. However, apparently, this is not true as the filter on the latter affects the filter of the former.
Is this a correct assumption? Should I start a different thread about this? I would love to understand why this is working this way.
Thanks!
UPDATE 3
---- SOLVED ---
This tidbit of information is not specifically stated in the documentation but you cannot have identical route names even though those route names are going to different REST verbs.
//routes.php BEFORE
Route::get('site/login', array('as'=>'site/login','uses'=>'HomeController#getLogin', 'before'=>'science'));
Route::post('site/login', array('as'=>'site/login', 'uses'=>'HomeController#postLogin',));
In the above solution, the 2nd Route OVERRIDES the previous route because the "as" uses the same name. I thought that these would be treated differently since one is GET and the other POST, but this is not the case. The filter assignments must happen by name in the backend and, as such, using identical names will override each other.
//routes.php AFTER
Route::get('site/login', array('as'=>'site/login','uses'=>'HomeController#getLogin', 'before'=>'science'));
Route::post('site/login', array('as'=>'site/postLogin', 'uses'=>'HomeController#postLogin',));
As you can see here, I renamed the 'as' part of the array to 'site/postLogin' and I can now use different filters for each the POST, GET, and probably PUT, DELETE and etc.
For better practice if two or more routes use the same filter, those routes should belong in a group. I have a feeling that will correct the issue.
From http://laravel.com/docs/routing#route-groups
Route::group(array('before' => 'auth'), function()
{
Route::get('/', function()
{
// Has Auth Filter
});
Route::get('user/profile', function()
{
// Has Auth Filter
});
});
---- SOLVED ---
This tidbit of information is not specifically stated in the documentation but you cannot have identical route names even though those route names are going to different REST verbs.
//routes.php BEFORE
Route::get('site/login', array('as'=>'site/login','uses'=>'HomeController#getLogin', 'before'=>'science'));
Route::post('site/login', array('as'=>'site/login', 'uses'=>'HomeController#postLogin',));
In the above solution, the 2nd Route OVERRIDES the previous route because the "as" uses the same name. I thought that these would be treated differently since one is GET and the other POST, but this is not the case. The filter assignments must happen by name in the backend and, as such, using identical names will override each other.
//routes.php AFTER
Route::get('site/login', array('as'=>'site/login','uses'=>'HomeController#getLogin', 'before'=>'science'));
Route::post('site/login', array('as'=>'site/postLogin', 'uses'=>'HomeController#postLogin',));
As you can see here, I renamed the 'as' part of the array to 'site/postLogin' and I can now use different filters for each the POST, GET, and probably PUT, DELETE and etc.

How can I shorten routes in Codeigniter for certain requests?

I have a page that has this category URL website.com/category/view/honda-red-car and I just want it to say http://website.com/honda-red-car no html or php and get rid of the category view in the URL.. this website has been done using the CodeIgniter framework..
also this product view URL website.com/product/details/13/honda-accord-red-car
and I want it to be website.com/honda-accord-red-car PLEASE HELP!!!
I cannot find correct instructions on what I am doing wrong??
In Routes.php you need to create one like so
$route['mycar'] = "controller_name/function_name";
So for your example it would be:
$route['honda-red-car] = "category/view/honda-red-car";
Take a look into the URI Routing part of the user guide.
If you have concrete set of urls that you want to route then by adding rules to the application/config/routes.php you should be able to achieve what you want.
If you want some general solution (any uri segment can be a product/details page) then you might need to add every other url explicitly to the routes.php config file and set up a catch-all rule to route everything else to the right controller/method. Remember to handle 404 urls too!
Examples:
Lets say the /honda-red-car is something special and you want only this one to be redirected internally you write:
$routes['honda-red-car'] = 'product/details/13/honda-accord-red-car';
If you want to generalize everything that starts with the honda- string you do:
$routes['(honda-.*)'] = 'product/details_by_slug/$1'; // imaginary endpoint
These rules are used inside a preg_replace() call passing in the key as the pattern, and the value as the replace string, so the () are for capture groups, $1 for placing the capture part.
Be careful with the patterns, if they are too general they might catch every request coming in, so:
$routes['(.*)'] = 'product/details_by_slug/$1';
While it would certainly work for any car name like suzuki-swift-car too it would catch the ordinary root url, or the product/details/42 request too.
These rules are evaulated top to bottom, so start with specific rules at the top and leave general rules at the end of the file.

Resources