Hello mn, when writing PHP about PHP, it is too normal, isn’t it, so how is it going to be written by RoR dev? I am a RoR dev, I’ve been moving to Laravel for a few months. Today I take the liberty to share with everyone about the policy in Laravel.
1. Overview of policy
What is policy?
- In my opinion, Laravel is one of the most powerful support frameworks I’ve ever known, everything you use is already integrated into the core laravvel or packages. One of them has authentication, and along with authentication, none other than authorization.
- There are two simple ways for you to decentralize your system supported by Laravel: Gate and Policy. Both are widely used and generally use Gate when you delegate things that are not related to any model or resource, for example, view an admininistrator dashboard page. In contrast, for Policy, you use permissions related to the model or resource.
- In this article I focus on sharing how to use Policy offline!
2. Working with policy
So to create yourself a policy, what to do, please follow these steps:
a) Initialize policy:
- First, you generate the corresponding policy file, Laravel has support for
make:policy
syntax to help you in this. - Within the scope of this article, I want to authorize the model Post. The syntax is as follows:
12php artisan make:policy PostPolicy - Mn noting that a mandatory policy suffix
Policy
follows the model or resource offline. - If you want to generate a file with both CRUDs, run the following command:
12php artisan make:policy PostPolicy --model=Post
b) Registration Policy:
- The next step is to register the policy. This registration helps App mapping between your model and the policy automatically.
123456789101112131415161718192021222324252627282930313233<span class="token php language-php"><span class="token delimiter important"><?php</span><span class="token keyword">namespace</span> <span class="token package">App Providers</span> <span class="token punctuation">;</span><span class="token keyword">use</span> <span class="token package">App Policies PostPolicy</span> <span class="token punctuation">;</span><span class="token keyword">use</span> <span class="token package">App Post</span> <span class="token punctuation">;</span><span class="token keyword">use</span> <span class="token package">Illuminate Foundation Support Providers AuthServiceProvider</span> <span class="token keyword">as</span> ServiceProvider <span class="token punctuation">;</span><span class="token keyword">use</span> <span class="token package">Illuminate Support Facades Gate</span> <span class="token punctuation">;</span><span class="token keyword">class</span> <span class="token class-name">AuthServiceProvider</span> <span class="token keyword">extends</span> <span class="token class-name">ServiceProvider</span><span class="token punctuation">{</span><span class="token comment">/*** The policy mappings for the application.** @var array*/</span><span class="token keyword">protected</span> <span class="token variable">$policies</span> <span class="token operator">=</span> <span class="token punctuation">[</span>Post <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token operator">></span> PostPolicy <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token keyword">class</span> <span class="token punctuation">,</span><span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token comment">/*** Register any application authentication / authorization services.** @return void*/</span><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">boot</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">registerPolicies</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token comment">//</span><span class="token punctuation">}</span><span class="token punctuation">}</span></span>
c) Implementing the policy
-
Policy methods
Just now we have just setup some basic things, now is the time for them to set up their policy according to their wishes. Assuming that I want to delegate as a User, I have the right to update only those posts of that User:
- We open the
PostPolicy.php
file, and add theupdate
method asPostPolicy.php
:
123456789101112131415161718192021<span class="token php language-php"><span class="token delimiter important"><?php</span><span class="token keyword">namespace</span> <span class="token package">App Policies</span> <span class="token punctuation">;</span><span class="token keyword">use</span> <span class="token package">App Post</span> <span class="token punctuation">;</span><span class="token keyword">use</span> <span class="token package">App User</span> <span class="token punctuation">;</span><span class="token keyword">class</span> <span class="token class-name">PostPolicy</span><span class="token punctuation">{</span><span class="token comment">/*** Determine if the given post can be updated by the user.** @param AppUser $user* @param AppPost $post* @return bool*/</span><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">update</span> <span class="token punctuation">(</span> User <span class="token variable">$user</span> <span class="token punctuation">,</span> Post <span class="token variable">$post</span> <span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">id</span> <span class="token operator">===</span> <span class="token variable">$post</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">user_id</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span></span>The method name in the policy you can set as you like is not necessarily the same as the method on the controller.
- Where there is no model
1234567891011/*** Determine if the given user can create posts.** @param AppUser $user* @return bool*/public function create(User $user){//}In the above example is the case of create Post, now there is no post object, then I only need 1 parameter as an instance of the User class for the create method.
- Policy filter:For certain users, you want them to have full control of the policy, so now you use the
before
method at the beginning of the Policy class. This method will execute before the other functions in Policy
1234567public function before($user, $ability){if ($user->isSuperAdmin()) {return true;}}
Following is the mapping table between the methods in the policy with the controller:
- We open the
d) Ways to use policy
- Use in Model :
1234if ($user->can('update', $post)) {//}
- Use in Middleware :
123456use AppPost;Route::put('/post/{post}', function (Post $post) {// The current user may update the post...})->middleware('can:update,post');
- Use in Controller :
1234567891011121314151617181920212223242526<?phpnamespace AppHttpControllers;use AppHttpControllersController;use AppPost;use IlluminateHttpRequest;class PostController extends Controller{/*** Update the given blog post.** @param Request $request* @param Post $post* @return Response* @throws IlluminateAuthAccessAuthorizationException*/public function update(Request $request, Post $post){$this->authorize('update', $post);// The current user can update the blog post...}}
- Using Authorizing Resource in Controller: Instead of writing
$this->authorize('update', $post);
In the controller action, Laravel supports them with an extreme method orauthorizeResource
. This method will add the corresponding authorization between the Policy and the Controller. Below is a mapping table between the methods in the Policy and Controller classes
Controller method Policy method index viewAny show view create create store create edit update destroy delete - There is a point to note, currently the index function on the controller cannot be mapped to viewAny in the policy. I searched gg then said the index was removed. Mn can refer to the fix as below or here :
12345678910111213class PostController extends Controller{public function __construct(){$this->authorizeResource(Post::class);}protected function resourceAbilityMap(){return array_merge(parent::resourceAbilityMap(), ['index' => 'view']);}}
- Use in Blade Templates :
123456789101112@can('update', $post)<!-- The Current User Can Update The Post -->@elsecan('create', AppPost::class)<!-- The Current User Can Create New Post -->@endcan@cannot('update', $post)<!-- The Current User Cannot Update The Post -->@elsecannot('create', AppPost::class)<!-- The Current User Cannot Create A New Post -->@endcannot
summary
Through the sharing above I hope you can grasp briefly what the policy is and how to use the policy appropriately.
Thanks MN for reading!
Happy Coding!