Use different route namespace based on middleware in Laravel - laravel

I have the following code in my routes/web.php
Route::namespace('Admin')->middleware(['admin'])->group(function() {
Route::get('/posts', 'PostController#index');
});
Route::namespace('User')->middleware(['user'])->group(function() {
Route::get('/posts', 'PostController#index');
});
I wish to use the same uri "/posts" in both cases and keep the role logic (admin, user) out of the controllers, however, in this case, when I request the route "/posts" in always responds with the last one.
I can't seem to find information of what I am missing here.

use prefix for different route for admin and user
/admin/posts
Route::group(['namespace' => 'Admin','middleware=>'admin','prefix' => 'admin'],function() {
Route::get('/posts', 'PostController#index');
});
/user/posts
Route::group(['namespace' => 'User','middleware=>'user','prefix' => 'user'],function() {
Route::get('/posts', 'PostController#index');
});

You may try this one
Route::group(['prefix'=>'admin','middleware'=>'admin'],function (){
Route::get('/posts',['uses'=>' PostController#posts','as'=>'posts.index']);
});
Route::group(['prefix'=>'user','middleware'=>'user'],function (){
Route::get('/index',['uses'=>' PostController#posts','as'=>'posts.index']);
});

Related

Laravel use multiple subdomains in one app

My question can we use something like this in laravel routing like one routes for admin.domain.com and other routes for clients.domain.com. How achieve this in laravel routing.
For example:
// these needs to go clients.domain.com/route
Route::get('/clients', 'App\Http\Controllers\HomeController#index')->name('clients');
Route::get('/clients/order', 'App\Http\Controllers\KuponaiController#pridetiKupona')->name('clients.order');
//this one to admin.domain.com/admin
Route::get('/admin', 'App\Http\Controllers\KuponaiController#patvirtinimokodas')->name('dashboard');
There is clear documentation on how you can use subdomains in your Laravel application here https://laravel.com/docs/8.x/routing#route-group-subdomain-routing.
Route::domain('{account}.myapp.com')->group(function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
For this to work, you need to have this subdomain before registering root domain routes
Create a route group and pass an array with a domain property:
Route::group(['domain' => 'clients.domain.com'], function()
{
// clients.domain.com/clients
Route::get('/clients', 'App\Http\Controllers\HomeController#index')->name('clients');
// clients.domain.com/clients/order
Route::get('/clients/order', 'App\Http\Controllers\KuponaiController#pridetiKupona')->name('clients.order');
});
Route::group(['domain' => 'admin.domain.com'], function()
{
// admin.domain.com/admin
Route::get('/admin', 'App\Http\Controllers\KuponaiController#patvirtinimokodas')->name('dashboard');
});

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 '-'

How Can i Call Middleware in this prefix Route?

Hello I am new in laravel framework. can anyone tell me how to apply middleware in this following route?
Route::prefix('Admin')->group(function (){
Route::get('/', 'UserlistController#index');
Route::post('create', 'UserlistController#create')->name('create');
});
There are various to call middleware in the group function.
1st way:- Define middleware after group function.
Route::prefix('Admin')->group(function (){
Route::get('/', 'UserlistController#index');
Route::post('create', 'UserlistController#create')->name('create');
})->middleware('yourmiddlewarename');
2nd way:- to define middleware with a prefix.
Route::middleware(['yourmiddlewarename'])->prefix('Admin')->group(function (){
Route::get('/', 'UserlistController#index');
Route::post('create', 'UserlistController#create')->name('create');
});
You should use Laravel's Route::group() method for proper grouping of routes.
You can group routes like the following:
Route::group(['as' => 'for_named_route','prefix' =>'for_prefixing','namespace' => 'for_namespacing', 'middleware' => 'for_middleware'],function(){
// Your route will go here
);
For your coding purpose your route group should be like the following:
Route::group(['prefix'=>'for_prefixing','middleware'=>'for_middleware'],function(){
// Your route will go here
Route::get('/', 'UserlistController#index');
Route::post('create', 'UserlistController#create')->name('create');
);
You can also pass multiple middleware using an array like:
'middleware'=>['middleware_1','middleware_2']
Route::group(['prefix'=>'admin','middleware'=>['auth']], function(){
Route::post('favorite/{post}/add','FavoriteController#add')->name('post.favorite');
Route::post('review/{id}/add','ReviewController#review')->name('review');
Route::get('file-download/{id}', 'PostController#downloadproject')->name('project.download');
Route::post('file-download/{id}', 'PostController#downloadproject');
});

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 add filter laravel

How add filter, when I logged in, and I enter user/login or user/register on url, I want to redirect to home.
and when I logged out, and I want to protect user/panel
Laravel has filters options the official website states the following for the filters
Route filters provide a convenient way of limiting access to a given route, which is useful for creating areas of your site which require authentication. There are several filters included in the Laravel framework, including an auth filter, an auth.basic filter, a guest filter, and a csrf filter. These are located in the app/filters.php file.
Defining a route filter
Route::filter('old', function()
{
if (Input::get('age') < 200)
{
return Redirect::to('home');
}
});
If the filter returns a response, that response is considered the
response to the request and the route will not execute. Any after
filters on the route are also cancelled.
Attaching a filter to the route
Route::get('user', array('before' => 'old', function()
{
return 'You are over 200 years old!';
}));
You can find complete documentation here
Route.php
Route::group(array('prefix'=>'user','before' => 'isUser'), function () {
Route::get('register', array('as' => 'register', 'uses' => 'UsersController#create'));
Route::get('login', array('as' => 'login', 'uses' => 'UsersController#login'));
// add post routes as required
});
filters.php
Route::filter('isUser', function ()
{
// I have used Sentry for user Authorisation
if (Sentry::check()) {
return Redirect::to('/')->with('message', "You are already logged in.");
}
else{
// benefit of using Redirect::guest() is that you can use Redirect::intended()
return Redirect::guest('login');
}
});

Resources