Laravel Middleware: Where should you put it as a best practice? - laravel

I was reading the Laravel documentation about middleware and at a certain point it said: "it would be more convenient to specify middleware within your controller's constructor."
I always assigned the middleware to the routes in the routing files because it felt easier to understand which functions were affected by the middleware.
I was wondering if there was a specific reason why the documentation says to put the middleware assignments directly in the Controller constructor or if it was just a matter of preference.

Its all depends on your own choice.
I always prefer to use middleware in route as a group, which keeps things centralized and I can find them easily.
Route::group(['middleware' => ['middleware1']], function () {
// your routes under middleware1
});
Route::group(['middleware' => ['middleware2']], function () {
// your routes under middleware2
});

I think it's a matter of preference, i like to assign the middleware to the route so i don't have to exclude certain methods in the controller plus it's much easier to know which routes use the middleware just by looking at the routes file.

it is more convenient to specify middleware within your controller's constructor.
This simply means you have more control over each methods if you use it in your controller's constructor, so that you can specify certain rules in method levels.
But when you are assigning to the routes you can only control the routes rules.

Thank you for your question, as mentioned before in most cases it is a decision made by the team you are working with.
From my own personal experience, I can only explain to you why we choose to use middleware definition in routes file instead of a controller.
In large applications, there are many cases of a dozen controllers.
With that being said, there can be cases where you have to change some middleware name. If you define it on route group you would have to change only one line of code, but if you define it in a constructor you would have to go to every controller and change it.
Some companies are using controllers to inject certainly classes into it. There can be a huge amount of injecting and assigning classes in the constructor itself.
That's why defining crucial checks should not be happening on this level of code.

Related

Controllers design pattern

I have a design question about MVC and controllers
I have this two routes
Route::get('/foo/{id}', FooController#show)
Route::get('/bar/{id}', BarController#show)
But know, I would like to add another route for the index like this
Route::get('/', ???)
In this route, I need some information about the Foo and Bar models.
The question is, should I create a new controller for that route? like MainController?
In general, controllers are meant to respond to requests associated with a specific resource (model). Thereby, given your concrete example, two distinct scenarios apply.
The Foo and Bar models are required on the landing page (/ route): In this case, a dedicated controller would be a perfectly fine thing to do. Also, the use of a view model would be beneficial.
No information about application-specific models is needed on the landing page: You can still use a dedicated controller class to return your view, while another possibility would be the use of a lambda function:
Route::get('/', function () {
return view('landing');
});
It has always worked best for me to have a controller per resource type.
You have the resource 'foo' with FooController, and 'bar' with BarController. So for the root context resource, you aught to have a root controller.
This helps with separation of concern and keeps your code modularized.

How to call the router from within a middleware in Laravel?

I'm building an api and I need to validate the key from within a middleware, so I want to call the router like this:
$this->getRouter()->input('key')
How would you go about this?
I also want to pass some results to the controller, so that I don't have to process the key again.
Assuming you're wanting to get the input as you say, the middleware already has the $request variable passed to it. You can simply call the key from the Request object given.
public function handle($request, Closure $next)
{
$key = $request->get('key');
...
If you're asking for the specifics of the route it's applied on you may need to rethink your strategy of what middleware does what. If you just wanted to massage the data and other various things for a specific controller then you may want to look into this being done on the controller constructor. If many controllers need it create a subcontroller of the parent controller that handles the key manipulation. Middleware as far as I know isn't meant to really handle business logic.
If this answer helped you out please mark it as so.

Named restful routes in Laravel 4

So, I've been able to get restful controllers working with
Route::controller('users','UserController');
class UserController extends BaseController {
public function getAccount(){}
}
and so /users/account works. However if I try to do something like
Route::any('account',array('as' => 'account','uses' => 'UserController#account'));
and go to /account, it doesn't work (NotFoundHTTPException). Is there a way to use named routes and restful controllers in conjunction? I like how the restful system breaks up requests, and how named routes encapsulate the URI's and decouple them from the function names. This worked in Laravel 3. Am I missing something in the syntax, or did Laravel 4 purposefully disallow this kind of mix-and-match behavior? Thanks...
This would depend entirely on the order you have defined the routes. If it's not working try reversing the order of the definitions.
But because Laravel is all about making your life easier you can pass an array of method names and their corresponding route name as the third parameter to Route::controller.
Route::controller('users', 'UsersController', ['getProfile' => 'user.profile']);
This might not directly apply to your situation but it is super handy.
Try this:
Route::get('/',array('as'=>'named_route','uses'=>'yourRestfulController#getMethod'));
This works nice for me. The trick was adding the action type after # part. You should use the full name of the method unlike in L3.
This works nice for me. The trick was adding the action type after # part. You should use the full name of the method unlike in L3.
Because REST prefix get, post, and so on are patterns to distinguish what type of REST it implements. When you named restful controllers route they didn't act like RESTful controllers anymore but a normal Controller you wish to named. Example of this:
Route::get('user/profile/', array('as'=>'dashboard', 'uses'=>'ProfileController#showDashboard'));
Consider this one:
Assuming we want SystemController to be a RESTful controller so you'll define:
Route::controller('/', 'SystemController');
Then you want to named the postDashboard on the SystemController as dashboard, so you'll modified your routes as:
Route::get('user/profile/', array('as'=>'dashboard','uses'=>'SystemController#postDashboard'));
Route::controller('/', 'SystemController');
On that scenario,postDashboard should not be access via GET protocol since we declared it to bePOST, that is if Laravel treated it as RESTful Controller, since we named it that way it will be treated as normal not RESTful, so we can access it tru GET protocol. Naming it that way will be so dramatically not appropriate, coz we are breaking what we want first which is telling Laravel to treat SystemController as a RESTful.
I think you have to consider the post of Jason Lewis as the appropriate answer. No hard feelings #arda, since you are also correct.

Transforming action name in route declaration

I'm wondering if there is a way to declare routes in MVC3 so that the route "zone1/{controller}/{action}" would direct to {controller}.zone1{action} method and "zone2/{controller}/{action}" would direct to {controller}.zone2{action} method, for example. So that's basically transforming the target action name based on the route.
Thanks
Check out The Attribute Routing project. You can specify on your methods the routes which I feel is a bit easier to read. Here's a decent blurb on it:
http://gregorsuttie.com/2012/01/12/attributerouting-for-mvc/
You could also write your own custom route handler but I don't believe you can do what you want without some custom code. I could be wrong here though. The attribute routing project should work just fine for what you want however.

Is it possible to use T4MVC with custom routes defined in global.asax?

I'd like to be able to use T4MVC with custom routes.
Is this possible and how do I use it? I've not seen anything generated in the strong helpers to be able to do this. Since the custom routes are just strings, I don't know if this is even possible.
If by custom route you mean 'named routes', then T4MVC indeed doesn't generate anything for them, as that would require parsing your code.
Instead, the simple thing to do is to just define a public constant with the route name, and use that both in the route definition and wherever you need to refer to the named route.

Resources