What does 'as' method do in Laravel - laravel

In the example from the tutorial, it shows up.
Route::group([
'prefix' => 'admin',
'as' => 'admin.'
], function () {}
Can someone tells me what 'as' does? Also, is the dot next to the 'admin' neccessary?
Thank you.

Let's say, for example, that you have this route:
Route::get('admin', [
'as' => 'admin', 'uses' => 'AdminController#index'
]);
By using as you assign custom name to your route. So now, Laravel will allow you to reference said route by using:
$route = route('admin');
So you don't have to build the URL manually over and over again in your code. You don't really need . notation if you only want to call your route admin. If you want a more detailed name of your route, lets say for ex. admin product route, then you use the . notation, like this:
Route::get('admin/product', [
'as' => 'admin.product', 'uses' => 'AdminController#showProduct'
]);
So now, you will be able to call this route by the assigned name:
$route = route('admin.product');
Update:
The previous answer I provided is valid for a single routes. For the route groups, the procedure is very similar. In the route groups you need the . notation when you add a custom name, since you will be referencing another route after that . notation. This will allow you to set a common route name prefix for all routes within the group. So by your example, lets say you have a dashboard route inside your admin route group:
Route::group(['as' => 'admin.'], function () {
Route::get('dashboard', ['as' => 'dashboard', function () {
//Some logic
}]);
});
Now, you will be able to call the dashboard route like this:
$route = route(admin.dashboard);
You can read more about this in Laravel official documentation.

you may specify an as keyword in the route group attribute array, allowing you to set a common route name prefix for all routes within the group.
For Example
Route::group(['as' => 'admin::'], function () {
// Route named "admin::"
});
UseRoute Name like {{route(admin::)}} or route('admin::')

you can use an 'as' as a named route. if you do not prefix your route name in group route than you may add custom route name like this.
Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'roles'], 'roles' => ['2']], function () {
Route::post('/changeProfile', ['uses' => 'UserController#changeProfile',
'as' => 'changeProfile']);
});

Related

How to set role name in prefix dynamically for same route group in laravel

I want to create dynamic prefix name according to logged user role name like for a same route group
if admin is login in admin panel then
url like :
http://localhost:8000/admin/dashboard
And, if dealer is login in admin panel :
http://localhost:8000/dealer/dashboard
my route group is
Route::group(['prefix' => 'admin', 'as' => 'admin.', 'namespace' => 'Admin', 'middleware' => ['auth', 'verified', 'preventBackHistory']], function () {
Route::get('/dashboard', 'HomeController#index')->name('home');
});
Basically My route group is same for admin & dealer
when i want different prefix according to user role when user is successfully login
It is a normal php file, so you may just add
if(...){ // if admin
$prefix = 'admin';
}else{ // if dealer
$prefix = 'dealer';
}
before your routes, and in your routes:
Route::group(['prefix' => $prefix, 'as' => $prefix.'.', 'namespace' => ucwords($prefix), 'middleware' => ['auth', 'verified', 'preventBackHistory']], function () {
Route::get('/dashboard', 'HomeController#index')->name('home');
});
Note: This is making a few assumptions about what you are doing.
You are not going to have access to the information about the current user until after the routes have been registered. The session has not started until after the request has been dispatched to a route and passes through the Middleware stack which will start the session. This is an idea of how to achieve that in a way that makes sense for the order of events.
You should setup the route group with a dynamic prefix:
Route::group(['prefix' => '{roleBased}', 'as' => 'admin.', 'namespace' => 'Admin', 'middleware' => ['auth', 'verified', 'dealWithPrefix', 'preventBackHistory']], function () {
Route::get('/dashboard', 'HomeController#index')->name('home');
});
Then in the RouteServiceProvider you will be adding a constraint for the prefix, parameter roleBased, to only allow it to be admin or client:
public function boot()
{
// restrict the prefix to only be 'admin' or 'dealer'
\Route::pattern('roleBased', 'admin|dealer');
parent::boot();
}
Now you will have to create a middleware to deal with getting the information of the current user to set a default for this prefix so that any URLs you generate to these routes will have this prefix and you don't have to pass a parameter for it. We will also remove the prefix parameter from the route so it does not get passed to your actions:
public function handle($request, $next)
{
$role = $request->user()->role; // hopefully 'admin' | 'client'
// setting the default for this parameter for the current user's role
\URL::defaults([
'roleBased' => $role
]);
// to stop the router from passing this parameter to the actions
$request->route()->forgetParameter('roleBased');
return $next($request);
}
Register this middleware in your kernel as dealWithPrefix. Note in the route group above this middleware was added to the list of middleware.
If you need to generate URLs to any routes in that group, and the current request isn't one of the routes in that group, you will be required to pass a parameter for this prefix when generating the URL:
route('admin.home', ['roleBased' => ...]);
If the request is currently for one of the routes in that group you will not need to add this parameter:
route('admin.home');
Note: This middleware could be applied in a wider way but you would need to know what default you want to use for this parameter if someone wasn't logged in. This is also assuming you may have more than just 1 route in that route group. If it is only that one single route then this can probably be adjusted slightly.

Laravel 5.4 route simplification

I've been trying to find some documentation on how to accomplish the following, but it seems like maybe I'm not using the correct search terms.
I would like to implement some simplified routes in Laravel 5.4 by omitting the route name from the path – for example:
/{page} instead of /pages/{page}
/profile instead of /users/{user}/edit
/{exam}/{question} (or even /exams/{exam}/{question}) instead of /exams/{exam}/questions/{question}
Example of current routes
Route::resource('exams.questions', 'ExamQuestionController', ['only' => ['show']]);
// exams/{exam}/question/{question}
I know how to do this with route closures and one-off routes (e.g.: Route::get...) but is there a way to do this using Route::resource?
In rails the above could be accomplished with:
resources :exams, path: '', only: [:index, :show] do
resources :question, path: '', only: [:show]
end
// /:exam_id/:id
While I haven't yet found a way to accomplish my test cases using strictly Route::resource, here is what I implemented to accomplish what I was trying to do:
// For: `/{exam}/{question}`
Route::group(['as' => 'exams.', 'prefix' => '{exam}'], function() {
Route::get('{question}', [
'as' => 'question.show',
'uses' => 'QuestionController#show'
]);
});
// For: `/exams/{exam}/{question}`
Route::group(['as' => 'exams.', 'prefix' => 'exams/{exam}'], function() {
Route::get('{question}', [
'as' => 'question.show',
'uses' => 'QuestionController#show'
]);
});
// For: `/profile`
Route::get('profile', function() {
$controller = resolve('App\Http\Controllers\UserController');
return $controller->callAction('edit', $user = [ Auth::user() ]);
})->middleware('auth')->name('users.edit');
// For: `/{page}`
// --------------
// Note that the above `/profile` route must come before
// this route if using both methods as this route
// will capture `/profile` as a `{page}` otherwise
Route::get('{page}', [
'as' => 'page.show',
'uses' => 'PageController#show'
]);
No, you cannot and should not be trying to do this with Route::resource.
The whole purpose of Route::resource is that it creates the routes in a specific way that matches the common "RESTful Routing" pattern.
There is nothing wrong with wanting simpler routes (no one is forcing you to use RESTful routing), but you will need to make them yourself with Route::get, etc. as you already know.
From the documentation (not exactly your case, but related to it - showing that Route::resource is not meant to be super-configurable):
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');

How to check domain in laravel for some routes?

I need check domain for some routes. Then after check, I need redirect domain https://two.com to https://one.com with middleware in laravel.
For example:
Routes:
Route::get('/', ['as' => 'index', 'uses' => 'IndexController#index']);
Route::get('termsAndCondition', ['as' => 'termsAndCondition', 'uses' => 'IndexController#termsAndCondition']);
Route::get('aboutUs', ['as' => 'aboutUs', 'uses' => 'IndexController#aboutUs']);
Route::get('privacy', ['as' => 'privacy', 'uses' => 'IndexController#privacy']);
I need check aboutUs and privacy for domain name.
If domain name is https://two.com/aboutUs or https://two.com/privacy redirect to https://one.com/aboutUs or https://one.com/privacy.
I need check with middleware.
Thanks.
You can do something like this in a middleware:
if (request()->getHttpHost() === 'two.com' && in_array(request()->path(), ['aboutUs', 'privacy'])) {
return redirect('https://one.com/' . request()->path());
}
you can check url segments using segment() helper something like:
if(Request::segment(1)==='aboutus')
{
return redirect(route('your other route');
}
if(Request::segment(1)==='privacy')
{
return redirect(route('your other route');
}
You can add that check in your middleware, segment() expects an integer param like in case above 1 will check first wildcard after domain name.

Get a parameter from a route?

I have the following route:
Route::get('news', [
'as' => 'news',
'uses' => 'ArticleController#getIndex',
]);
There are also other routes that use the same resource controller, e.g:
Route::get('travel', [
'as' => 'travel',
'uses' => 'ArticleController#getIndex',
]);
In the article controller, how can I get the category of the articles. e.g. travel or news?
I can't turn it into a route param e.g.
Route::get('{travel}', [
'as' => 'travel',
'uses' => 'ArticleController#getIndex',
]);
As there are other sections such as contact, faqs, etc that do not use the article controller.
I know I could put it all on one route:
Route::get('/article/{category}', [
'as' => 'travel',
'uses' => 'ArticleController#getIndex',
]);
But I want pretty URLS like:
mydomain.com/category-slug/article-slug
Ideally if I could use a resource controller:
Route::resource('news', ArticleController');
With some sort of array:
Route::resource(['news', 'travel'], ArticleController');
So my questions:
How can I get the name of the resource. e.g. news, travel in my controller?
Is there an easy way to specify varying routes to the same resource?
For Example Keep your routes like this as your static routes will be limited and need to be unique so they will not get conflict between routes
demo routes :
Route::get('contact', [
'as' => 'contact',
'uses' => 'contactController#getIndex',
]);
Route::get('{travel}', [
'as' => 'travel',
'uses' => 'ArticleController#getIndex',
]);
In order to achieve a route like that:
mydomain.com/category-slug/article-slug
Use the following:
Route::get('/{category}/{article}', 'ArticleController#getArticle');
Then in your controller, you will have 2 parameters in your getArticle method.
public function getArticle($category, $article)
{
//Your code here
}
In order to have pretty urls you need to make a few steps:
1)
First of all you need to add a column to your articles table called for example 'slug'.
2) Then you need to specify your route key in your article model. Like this:
Article model
public function getRouteKeyName()
{
return 'slug';
}
3) When you add an article you should create the slug by your own in order to be unique. so in your controller that you create the article add this code.
$slug = str_slug($article['title'], '-');
$slugs_count = DB::table('articles')->where('name',$article['title'])- >count();
if($slugs_count>1){
$slug = $slug.'-'.($slugs_count-1);
}
$article->slug = $slug;
$article->update();
4) Now we have to set the route
Route::get('/article/{slug}', [
'as' => 'travel',
'uses' => 'ArticleController#getIndex'
])->where(['slug','[\w\d\-\_]+']);
5) Finally in order to get the article you need
$article = Article::where('slug','=',$slug)->first();
If you want to use categories etc you could pass more parameters in your route and manipulate it in your controller. like this
Route::get('/article/{category}/{slug}', [
'as' => 'travel',
'uses' => 'ArticleController#getIndex'
])->where(['slug','[\w\d\-\_]+','category','[\w\d\-\_]+']);
The where clause is to restrict the parameter with some regular expressions(its optional).
I forgot to mention that the routekeyname in your model works in laravel 5.2.

LARAVEL: How to use middleware on named routes

I've been working on an app that initially didn't use middleware. Later on, I decided to add middleware and had to change my routes from something like:
Route::get('admin/poems', array('as' => 'poems', 'uses' => 'PoemsController#poem'));
to
Route::get('admin/poem', ['middleware' => 'auth', 'uses' => 'PoemsController#poem']);
Now the disadvantage is that I had been redirecting to this route (poems) several times and adding middleware as indicated will require me to go through all my code and change the name of the route in the redirect.
How do i solve this problem?
Thanks for any help.
You don't need to lose the name of your route, the array will still accept it along with your middleware.
Just add it in to look like so:
Route::get('admin/poem', ['middleware' => 'auth', 'as' => 'poems', 'uses' => 'PoemsController#poem']);
This way you don't need to go through and rename your routes anywhere and can still protect it with auth middleware.
try put middleware to a group route
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});

Resources