You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Laravel嵌套资源控制器的两个show方法创建独立Policy?

实现步骤

1. 生成两个独立的Policy

执行Artisan命令生成对应的策略类:

php artisan make:policy CompanyAddressPolicy
php artisan make:policy UserAddressPolicy

2. 实现策略类逻辑

CompanyAddressPolicy(公司地址权限)

路径:app/Policies/CompanyAddressPolicy.php

<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Company;
use App\Models\Address;

class CompanyAddressPolicy
{
    /**
     * 判断用户是否可查看公司地址
     */
    public function view(User $currentUser, Company $company, Address $address): bool
    {
        // 安全校验:确保当前地址属于指定公司,避免参数篡改越权
        if ($address->addressable_id !== $company->id || $address->addressable_type !== Company::class) {
            return false;
        }

        // 权限判断:A、B角色可查看,C无权限
        // 此处可替换为你实际的权限判断逻辑,如权限标签、角色表判断等
        return in_array($currentUser->role, ['A', 'B']);
    }
}

UserAddressPolicy(用户地址权限)

路径:app/Policies/UserAddressPolicy.php

<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Address;

class UserAddressPolicy
{
    /**
     * 判断用户是否可查看用户地址
     */
    public function view(User $currentUser, User $targetUser, Address $address): bool
    {
        // 安全校验:确保当前地址属于指定用户,避免参数篡改越权
        if ($address->addressable_id !== $targetUser->id || $address->addressable_type !== User::class) {
            return false;
        }

        // 权限判断:仅A角色可查看
        return $currentUser->role === 'A';
    }
}

3. 控制器中调用授权

嵌套资源场景下,不需要把策略绑定到Address模型(避免同模型多策略冲突),直接在对应方法中手动指定策略类调用授权即可:

CompanyAddressController 调整

class CompanyAddressController {
    public function show(Request $request, Company $company, Address $address)
    {
        // 传入策略类 + 路由参数(参数顺序和策略方法的参数顺序保持一致)
        $this->authorize('view', [CompanyAddressPolicy::class, $company, $address]);
        
        // 原有业务逻辑
    }
}

UserAddressController 调整

class UserAddressController {
    public function show(Request $request, User $user, Address $address)
    {
        $this->authorize('view', [UserAddressPolicy::class, $user, $address]);
        
        // 原有业务逻辑
    }
}

可选:全控制器资源自动授权方案

如果需要给控制器所有资源方法做授权,可以通过创建代理模型的方式实现authorizeResource自动绑定:

  1. 给两类地址创建继承自Address的空代理模型:
// app/Models/CompanyAddress.php
class CompanyAddress extends Address
{
    // 无需额外逻辑,仅做策略绑定标识
}

// app/Models/UserAddress.php
class UserAddress extends Address
{
}
  1. 在app/Providers/AuthServiceProvider.php的$policies数组中注册绑定:
protected $policies = [
    // 其他已有绑定
    \App\Models\CompanyAddress::class => \App\Policies\CompanyAddressPolicy::class,
    \App\Models\UserAddress::class => \App\Policies\UserAddressPolicy::class,
];
  1. 控制器中开启自动授权,参数替换为对应代理模型:
class CompanyAddressController {
    public function __construct()
    {
        // 第二个参数对应路由中的地址参数名address
        $this->authorizeResource(CompanyAddress::class, 'address');
    }

    public function show(Request $request, Company $company, CompanyAddress $address)
    {
        // 无需手动调用authorize,自动完成授权校验
    }
}

内容的提问来源于stack exchange,提问作者jhine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 22:30:04