How to call the router from within a middleware in Laravel? - 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.

Related

Laravel do i need two controllers to handel two store functions?

Basically what i want to do is that 1 Controller handels two store functions called like this:
public function singleupload(){
..some code
}
and
public function multiupload(){
..some code too
}
as i continued to define the routes (get/post)
Route::get('/MultiUpload', 'controller#MultiUpload');
Route::get('/SingleUpload', 'controller#SingleUpload');
Route::post('/MultiUpload', 'controller#storeMulti');
Route::post('/SingleUpload', 'controller#storeSingle');
and as i tried to post some data to my database it tells me that there is no 'store' function. So i opened the docs and found this:
POST /photos store photos.store
So my question is can i create two store functions in one controller or do i have to create a different one so every route has its own controller with its own store function?
You are doing some things wrong.
First of all follow Repository Pattern.
You should always write all common functions in Repository which can be accessible in entire Project.
You should use controller only to fetch the request from the Route and pass all the logic to the Repository.
These Process will help you reduce all you coding lines.
Hope this helps !!!
cheers!!
NO you don't need to create new Controller. You can add new action for this.
But it also, depends on the how is your application functionality.
Normally, i personally recommended to create generic function or traits or add the functionality in base controller.
you can handle multiple store functions in one controller there is no need to create 2 different controllers.

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

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.

Laravel 5.1 index & create authorization

I'm using Laravel 5.1's authorization features, documented here. My controllers implement AuthorizesRequests and I have my policies set up connecting policies to their models to create an ACL of sorts. In my controllers, I'm checking for authorization in each method. For example, in an 'AgencyController' the 'update' method calls $this->authorize($agency), which then checks my AgencyPolicy's update method to know rather or not the current user is allowed to update the agency, just as described in the documentation. This works the way I want it to.
However, what I can't seem to figure out is how to use authorization for other methods like index() and create() where there isn't a specific model being used. Calling $this->authorize('index') seems to return false, even if I have an index($user) function in my policy class that only returns true.
I'm new to using Laravel's authorization helpers, so I might be going about this wrong or missing something obvious. Any help pointing me in the right direction would be gretaly appreciated!
You have to pass it the class name of the model you're checking:
$this->authorize('index', Agency::class);
With some help from someone in the Laravel slack group I was able to find the answer to this myself.
Without an instance of the model, the authorize() calls couldn't map to the correct policies. But by simply passing the class to them, it is able to and works.
For example, instead of calling $this->authorize('index') in my controller's index method, I'm now calling $this->authorize('index', Agency::class) to give it the correct model to use.

Authorization Policy without model

I need to authorize users on a forum.
So in blade, I have #can('editPost', $post) before showing the form to reply to a topic. My PostPolicy class has a editPost method that validates to true if it's the users own post.
However, the issue appears when I want to do a simple check, like deletePost(). This checks to see if Auth::user()->isAdmin
public function deletePost(User $user) {
return Auth::user()->isAdmin;
// return $user->isAdmin
}
However, this won't even get called, since I'm not passing an instance of Post
My real world application is much more complicated, but I'm using isAdmin as a simple example.
I guess defining $gate->define('deletePost', 'App\Policies\PostPolicy#deletePost'); in AuthServiceProvider could work, but would end up separating my definitions and methods, and ultimately for a large app clutter the AuthServiceProvider
When you register a policy it is the classname that is used to route checks to the class, so in order to get routed to the policy you can just pass the class name of the type you registered it with.
Try using #can('delete', Post::class) and see if that gets you there
refer to
Illuminate\Auth\Access\Gate::firstArgumentCorrespondsToPolicy
EDIT
After a little more diggin I found this
https://github.com/laravel/framework/commit/70f75255808ffc96275e6f2f356616dd2e163434#diff-961368895033e553787b301c3be0e17a
so it looks like if you on version 5.1.23 then you will be able to pass a string otherwise your will need to just pass new Post
In controllers
$this->authorize('<ability>', <Class-With-Rule::class> | <Full-Path-To-Class>);
In Blade view
#can('<ability>', <Class-With-Rule>::class> | <Full-Path-To-Class>)
In Eloquent model
$user->can('<ability>', <Class-With-Rule>::class> | <Full-Path-To-Class>);
Methods Without Models:
Some policy methods only receive the currently authenticated user and not an instance of the model they authorize. This situation is most common when authorizing create actions. For example, if you are creating a blog, you may wish to check if a user is authorized to create any posts at all.
When defining policy methods that will not receive a model instance, such as a create method, it will not receive a model instance. Instead, you should define the method as only expecting the authenticated user:
https://laravel.com/docs/7.x/authorization

How do I pass arguments / parameters to model

Following the tutorial how to create a joomla 2.5 component I'm stucked to pass arguments from view.html.php to my model.
$items = $this->get('TableData');
and my TableData model would expect to get the following arguments
public function getTableData($table, $index_column, $columns) {}
You can not do this using the view's get method. Instead you would have to grab the model into the view and call the function directly in the view:
$model = $this->getModel();
$items = $model->getTableData($table, $index_column, $columns);
Alternately, you could create different entry points in the model that would be able to figure these input options either from state information or preset. Many would argue that this would lead to a better application design, since using my code above is putting what should be model logic in the view.
This is just an addon to David's answer.
Because most of the data usually comes from POST / GET methods, depending on your application, you may want to look at how loadFormData() from loadFormData JModelForm or populateState gets overridden in specific Joomla components.
Basically the state of model is set directly from POST data, using JInput.
Also, although it's not a rule or something, 3 parameters is a maximum I would pass to a method. For flexibility I would rather pass an array with can be later extended without changing the method signature.

Resources