// 第一個參數為規則名稱
// 第二個參數為一個可以回傳 boolean 的 closure
// closure 第一個參數為 user 實例, 第二個參數以後為要驗證的資料(可以多個)
Gate::('update-product', function($user, $product) {
// ... 回傳 boolean
return $user->id === $product->user_id;
});
php artisan make:policy ProductPolicy
class ProductPolicy {
public function update($user, $product) {
return $user->id == $product->user-id;
}
// 可以設定 before() 覆寫其他權限
public function before($user, $ability) {
if( $user->isAdmin() ) {
return true;
}
}
}
// 於 AuthServiceProvider
class AuthServiceProvider extends ServiceProvider {
protected $policies = [
Product::class => ProductPolicy::class
];
}
// 相對應於路由 product.view、 product.create、 product.update、product.delete
Gate::resource('product', 'App\Policies\ProductPolicy');
// middleware 設定第一個為要執行的規則名稱, 第二個是物件的 id
// 若要檢查的並不是實例, 可以將 id 替換成 Class e.g. App\Models\Product
Route::get('product/{id}/edit', functoin(){
// ... 修改商品
})->middleware('can:edit,id');
Controller 授權檢查
public function edit(Product $product) {
// 當失敗時會回傳 403 並退出程式
$this->authorize('update-product', $product);
return view('product.edit', ['product' => $product]);
}
// 可以切換使用非當下登入 user
$this->authorizeForUser($user, 'update-product', $product);
class ProductController extends Controller {
public function __construct() {
// 設定完後可以移除其他 function 內的 authorize 驗證
$this->authorizeResource(Product::class);
}
}
用戶實例授權檢查
@can('edit-product', $product)
<a href="{{ route('edit-product', ['product' => $product->id]) ">修改</a>
@endcan
// 可在 AuthServiecProdvider 指定
// $ability 為規則的字串名稱, 可用此來區隔要執行的檢查
Gate::before(function( $user, $ability ) {
if ( $user->isOwner() ) {
return true;
}
});
// 使用 Gate 靜態介面
// 此時會呼叫 ProductPolicy 內的 update() 方法檢查
if(Gate::denies('update', $product)) {
abort(403);
}
// 使用 user 檢查
if( $user->can('update', $product)) {
// 執行要做的動作
}
// 使用全域方法 policy() 取回一個 policy 實例並執行他的方法
if(policy($product)->update($user, $product)) {
// 執行要做的動作
}