Laravel route group prefix - variable not working - laravel

in web.php :
Route::group(['middleware'=>['checklang','checkmoney']],function(){
Route::get('/', function () {
return redirect('/'.session()->get('lang'));
});
Route::group([
'prefix' => '{locale}',
'where'=>['locale'=>'[a-zA-Z]{2}']],
function() {
Route::get('/tour/{id}','HomeController#getTours');
});
});
in HomeContoller :
public function getTours($id){
dd($id);
}
when trying to access url : example.com/en/tour/5
getting result
en , but should be 5
Where is a problem and how to solve it?

Your route has 2 variables, {locale} and {id}, but your Controller method is only referencing one of them. You need to use both:
web.php:
Route::group(['prefix' => '{locale}'], function () {
...
Route::get('/tour/{id}', 'HomeController#getTours');
});
HomeController.php
public function getTours($locale, $id) {
dd($locale, $id); // 'en', 5
}
Note: The order of definition matters; {locale} (en) comes before {id} 5, so make sure you define them in the correct order.

Related

Laravel route group with variable prefix and where condition

I would like to create a route group in Laravel with a variable as a prefix. I need to set certain conditions too. How to do it properly?
I was following docs: https://laravel.com/docs/8.x/routing#route-group-prefixes but there are only general examples.
This code should create 2 routes: /{hl}/test-1 and /{hl}/test-2 where {hl} is limited to (en|pl), but it gives an error: "Call to a member function where() on null"
Route::prefix('/{hl}')->group(function ($hl) {
Route::get('/test-1', function () {
return 'OK-1';
});
Route::get('/test-2', function () {
return 'OK-2';
});
})->where('hl','(en|pl)');
The group call doesn't return anything so there is nothing to chain onto. If you make the where call before the call to group, similarly to how you are calling prefix, it will build up these attributes then when you call group it will cascade this onto the routes in the group:
Route::prefix('{hl}')->where(['h1' => '(en|pl)'])->group(function () {
Route::get('test-1', function () {
return 'OK-1';
});
Route::get('test-2', function () {
return 'OK-2';
});
});
By analogy with this answer:
Route::group([
'prefix' => '{hl}',
'where' => ['hl' => '(en|pl)']
], function ($hl) {
Route::get('/test-1', function () {
return 'OK-1';
});
Route::get('/test-2', function () {
return 'OK-2';
});
});
Does this solve your problem?

Laravel Route: Multiple Route Group With Prefix and Route Model Binding

Hello wonderful people of SO!
I have a problem about Laravel Route which I cannot solve.
In User.php model I use getRouteKeyName() function
public function getRouteKeyName()
{
return 'user_name';
}
And also in Post.php model
public function getRouteKeyName()
{
return 'uuid';
}
In users table, 1 have one record
|----------------------------|
| id | ... | user_name | ... |
| 1 |-----| #simple |-----|
In posts table
|------------------------------------|
| id | ... | uuid | ... |
| 1 |-----| abcd-123-efg-456 |-----|
In route (web.php)
// for post (key: uuid)
Route::group(['prefix' => '{post}'], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
// for users (key: user_name)
Route::group(['prefix' => '{user}'], function () {
Route::get('/', function (User $user) {
return $user;
});
});
Then let say we visit url: www.example.test/#simple/
In debugbar, I see query:
select * from posts where uuid = '#simple' limit 1
What I have tried
[#1] I put where clause in route groups for posts and users
Route::group([
'prefix' => '{post}',
'where' => [
'post' => '^[a-zA-Z0-9-]{36}$' // I'm not Regex professional
]
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => '{user}',
'where' => [
'user' => '^(#)[a-zA-Z0-9]$' // I'm not Regex professional
]
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
So let's try again visit the url: www.example.test/#simple
What i got, 404
[#2] I deleted the getRouteKeyname in both User and post model
revisit url: www.example.test/#simple, still got 404
[#3] I tried to put Route Model Binding Column Name
Route::group([
'prefix' => '{post:uuid}', // This is what I changed
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => '{user:user_name}', // This is what I changed
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
Still, query result is same: > select * from posts where uuid = '#simple' limit 1
What I want to achieve
Let say we visit url: www.example.test/#simple
Fetch a user with user_name is #simple or if the user is not exist, return 404
And also same for with posts
We visit url: www.example.test/abcd-1234-efgh-5678
Fetch a post with uuid is abcd-1234-efgh-5678 or 404 if not exist
Question:
[#1] How to tell Laravel Route: that I have 2 Route groups with different Model Binding? Sorry if this question is kinda confusing, cause my english is not really good
[#2] Have I implement Best practice for route groups and route model binding in Laravel?
Thanks in advance!
What is the result you intend to obtain?
If you are doing what I think you're doing (trying to see what's inside the post), you need to return something like $post->content (replace content with the column you want to get), you may even want to make a view and make the output nicer, plus use a controller for more processing.
As for route model binding, you can refer to this, both methods, using table:column and using getRouteKeyName are fine, however, the first one doesn't change the default column, and if you use {user} for another route, it will still use the ID column, however, the second one changes the default value, if you use {user} for another route, it will use the column you specified.
Also, you should use something like user/{user:user_name} and post/{post:uuid} instead of just {user:username} and {post:uuid}, as you have said, it won't know which route you're using. The uri has to be different.
Routes are evaluated in the order you put them, meaning that the second route with {post:uuid} will override the route with {user:username} since they have the same kind of uri, that is, they both consist of 1 wildcard and nothing else. To solve this, you simply have to make their uri different by adding a static part, for example, add post/ before {post:uuid} and/or add user/ before {user:user_name} like the example below:
Route::group([
'prefix' => 'post/{post:uuid}',
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => 'user/{user:user_name}',
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
To make it very clear, your 2 routes have the same uri of 1 wildcard and nothing else, thus, the last one that appears with this uri will override all the previous routes with the same uri. Meaning that all the previous routes with this same uri before this will be treated like they don't exist, and when you go to a path with the uri in the format of /[insert something here], it fits into the format of having 1 wildcard and it will only go to the last one you specified, that is, the one for posts.
Since the route for users is declared before the one for posts and they share the same uri, only the one for posts will be used. Even when you are trying to find the user, it still uses the route for posts, if no such "post" with a uuid same as the user_name you provided exists, it will still return an error even when there is indeed such user with such username.
Also, you don't need a route group if there's simply 1 route, though it would be more readable and convenient if you're going to add more routes to the group in the future.
As far as I could understand your problem, here are the changes you need to make and it will work,
routes/web.php
Route::group([
'prefix' => 'post/{post:uuid}'
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => 'user/{user:user_name}'
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
Regular Expression that you use above just does filter the {argument} and check if {argument} is alphanumeric basically, in above both cases it works the same except in user_name it also allows '-'

Laravel build multi-lang route system

im using Laravel 5, and i have this route:
Route::group(['prefix' => '{lang}/', 'middleware' => 'SetLanguage'], function($lang){
//element Show
Route::get('/'.trans('routes.element-container').'/{slugName}', 'ElementController#showByName');
});
My middleware is this:
public function handle($request, Closure $next)
{
if (in_array($request->lang, config('app.all_langs'))){
//exit("SETTING ON ".$request->lang);
App::setLocale($request->lang);
}else{
//exit("SETTING ON en");
App::setLocale('en');
}
return $next($request);
}
If i un-comment the two exit it works, but, the function "trans" on route side is not working, seems to trans only in default lang.
why the "trans" function is called before the middleware?
I have test with 'before' and 'after', but no work...
If I understood you correctly, you could consider something like this:
Route::group(['prefix' => '{lang}/', 'middleware' => 'SetLanguage'], function() {
foreach (config('app.all_langs') as $language) {
$translatedRoute = trans('routes.element-container', [], $language);
Route::get("/$translatedRoute/{slugName}", 'ElementController#showByName');
}
});
But this will also register routes for e.g. /de/element-container/element-a.
Alternative:
foreach (config('app.all_langs') as $language) {
Route::group(['prefix' => $language, 'middleware' => 'SetLanguage'], function() {
$translatedRoute = trans('routes.element-container', [], $language);
Route::get("/$translatedRoute/{slugName}", 'ElementController#showByName');
});
}
This will register /en/element-container/element-a and /de/Elemente-Behälter/element-a, but not /de/element-container/element-a

How to add dynamically prefix to routes?

In session i set default language code for example de. And now i want that in link i have something like this: www.something.com/de/something.
Problem is that i cant access session in routes. Any suggestion how can i do this?
$langs = Languages::getLangCode();
if (in_array($lang, $langs)) {
Session::put('locale', $lang);
return redirect::back();
}
return;
Route::get('blog/articles', 'StandardUser\UserBlogController#AllArticles');
So i need to pass to route as prefix this locale session.
If you want to generate a link to your routes with the code of the current language, then you need to create routes group with a dynamic prefix like this:
Example in Laravel 5.7:
Route::prefix(app()->getLocale())->group(function () {
Route::get('/', function () {
return route('index');
})->name('index');
Route::get('/post/{id}', function ($id) {
return route('post', ['id' => $id]);
})->name('post');
});
When you use named routes, URLs to route with current language code will be automatically generated.
Example links:
http://website.com/en/
http://website.com/en/post/16
Note: Instead of laravel app()->getLocale() method you can use your own Languages::getLangCode() method.
If you have more questions about this topic then let me know about it.
Maybe
Route::group([
'prefix' => Languages::getLangCode()
], function () {
Route::get('/', ['as' => 'main', 'uses' => 'IndexController#index']);
});

how to use the laravel subdomain routing function

I am using the following code its from the laravel 4 site
Route::group(array('domain' => '{account}.myapp.com'), function() {
Route::get('user/{id}', function($account, $id) {
// ...
return Redirect::to('https://www.myapp.com'.'/'.$account);
});
});
the idea is to redirect subdomain.myapp.com to myapp.com/user/subdomain
.what I have is not working any suggestions?sorry I just started with laravel about a month now.
Remove user/{id} and replace it with / and then use the following url https://accountname.myapp.com and it will redirect to https://www.myapp.com/accountname
Route::group(array('domain' => '{account}.myapp.com'), function() {
Route::get('/', function($account, $id) {
// ...
return Redirect::to('https://www.myapp.com'.'/'.$account);
});
});
Edit the answer to the correct answer
Route::group(array('domain' => '{account}.myapp.com'), function() {
Route::get('/', function($account) {
// ...
return Redirect::to('https://www.myapp.com/'.$account);
});
});
as Marc vd M answer but remove $id from get's closure function.
why use 'https://www.myapp.com'.'/'.$account and not 'https://www.myapp.com/'.$account

Resources