PHP 怎么PHP 字段权限

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 字段权限

  1. 基础方案:角色判断 + 逻辑过滤(最常用)
  2. 数据库层:查询时动态选择字段
  3. 通用方案:权限配置 + 中间件(推荐)
  4. 框架级方案(以 Laravel 为例)
  5. 终极方案:读写分离权限(复杂场景)
  6. 总结对比

在 PHP 中实现“字段权限”通常指控制谁能访问或修改数据表的某个字段(普通用户不能查看 salary 字段,管理员才能编辑 is_admin 字段)。

下面是几种常见的实现方案,从简单到专业:


基础方案:角色判断 + 逻辑过滤(最常用)

在查询数据库后,根据用户角色对结果数组进行字段过滤。

<?php
function filterFieldsByRole(array $data, string $role): array
{
    // 定义不同角色的可见字段
    $fieldPermissions = [
        'admin' => ['id', 'name', 'email', 'salary', 'phone'],
        'user'  => ['id', 'name', 'email'],
        'guest' => ['id', 'name'],
    ];
    $allowedFields = $fieldPermissions[$role] ?? []; // 默认为空
    // 只保留允许的字段
    return array_intersect_key($data, array_flip($allowedFields));
}
// 使用示例:
$userData = [
    'id'     => 1,
    'name'   => 'Alice',
    'email'  => 'alice@example.com',
    'salary' => 50000,
    'phone'  => '1234567890'
];
$currentUserRole = 'user';
$filteredData = filterFieldsByRole($userData, $currentUserRole);
print_r($filteredData);
// 输出:Array ( [id] => 1 [name] => Alice [email] => alice@example.com )

优点:简单直接,适合中小项目。
缺点:硬编码权限,数据库返回大字段集再过滤,效率略低。


数据库层:查询时动态选择字段

更适合高性能要求(只查询需要的字段,减少网络传输)。

<?php
function getUserFieldsByRole(string $role): array
{
    $fieldMap = [
        'admin' => ['id', 'name', 'email', 'salary'],
        'user'  => ['id', 'name', 'email'],
        'guest' => ['id', 'name'],
    ];
    return $fieldMap[$role] ?? ['id']; // 兜底至少返回 id
}
// 构建查询
$role = 'user';
$fields = getUserFieldsByRole($role);
$fieldStr = implode(', ', $fields);
$query  = "SELECT {$fieldStr} FROM users WHERE id = ?";
// 然后使用 PDO 执行 $query...

优点:数据库只返回可见字段,减少 I/O。
缺点:仍依赖硬编码;复杂权限(如字段级读写分离)需要更细粒度控制。


通用方案:权限配置 + 中间件(推荐)

将权限定义放在配置文件中,结合一个拦截器统一处理。

1 权限配置文件 permissions.php

return [
    'User' => [                          // 模型或资源名
        'fields' => [
            'salary' => ['admin', 'hr'], // 只有 admin 和 hr 可见
            'phone'  => ['admin'],
            'email'  => ['admin', 'user', 'hr'],
            '*'=> ['admin', 'user', 'hr', 'guest'] // 默认所有角色可见
        ]
    ]
];

2 权限检查类

<?php
class FieldPermission
{
    private array $config;
    private string $userRole;
    public function __construct(array $config, string $userRole)
    {
        $this->config   = $config;
        $this->userRole = $userRole;
    }
    public function filter(string $resource, array $data): array
    {
        $fieldsConfig = $this->config[$resource]['fields'] ?? [];
        $result = [];
        foreach ($data as $field => $value) {
            if ($this->isFieldAllowed($field, $fieldsConfig)) {
                $result[$field] = $value;
            }
        }
        return $result;
    }
    private function isFieldAllowed(string $field, array $fieldConfig): bool
    {
        // 如果有该字段的特定权限
        if (isset($fieldConfig[$field])) {
            return in_array($this->userRole, $fieldConfig[$field]);
        }
        // 否则使用默认权限(*)
        $default = $fieldConfig['*'] ?? ['*']; // *表示所有角色
        return in_array($this->userRole, $default) || in_array('*', $default);
    }
}

3 使用

$config   = require 'permissions.php';
$checker  = new FieldPermission($config, 'user');
$safeData = $checker->filter('User', $userData);

优点:配置与逻辑分离,易维护,支持任意角色。
缺点:需要额外加载配置和处理。


框架级方案(以 Laravel 为例)

Laravel 可以使用 Policy(策略) + Resource(API 资源) 实现字段权限。

1 创建 Policy

php artisan make:policy UserPolicy --model=User

2 在 Policy 中定义 visibleFields

public function visibleFields(User $user) : array
{
    if ($user->isAdmin()) {
        return ['*'];  // 全部可见
    }
    return ['id', 'name', 'email'];
}

3 使用 API Resource 过滤

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        $allowed = $request->user()->can('visibleFields', $this->resource) 
            ? $this->resource->toArray() 
            : array_intersect_key(
                $this->resource->toArray(), 
                array_flip(['id', 'name', 'email'])
              );
        return $allowed;
    }
}

优点:深度集成框架,支持依赖注入、缓存等。
缺点:学习成本较高。


终极方案:读写分离权限(复杂场景)

如果需要不同的字段在读取和修改时有不同权限

字段 读权限 写权限
salary admin, hr admin
phone admin admin, user
email admin, user admin, user, hr

可扩展上面的方案为:

$permissions = [
    'User' => [
        'salary' => ['read' => ['admin','hr'], 'write' => ['admin']],
        'phone'  => ['read' => ['admin'],     'write' => ['admin','user']],
        'email'  => ['read' => ['admin','user'], 'write' => ['admin','user','hr']],
        '*'      => ['read' => ['*'], 'write' => ['*']],
    ]
];

然后检查时需提供操作类型 $operation = 'read''write'


总结对比

方案 复杂度 灵活性 推荐场景
角色 + 逻辑过滤 ⭐低 ⭐低 简单、快速原型
数据库层动态选字段 ⭐中 ⭐中 性能敏感、接口统一
配置化中间件 ⭐⭐中 ⭐⭐高 中型项目,需快速调整权限
框架集成 (Laravel等) ⭐⭐⭐高 ⭐⭐⭐高 大型项目,团队规范
读写分离权限 ⭐⭐⭐高 ⭐⭐⭐高 复杂业务(金融、人事系统)

建议:从方案3(配置化中间件)开始,它兼顾扩展性和开发效率,未来升级到框架集成也很容易。

抱歉,评论功能暂时关闭!