Hyperf 组织架构基础包,提供企业、部门、员工、角色、权限、数据隔离等完整功能。支持企业级和用户级两种数据隔离方式,内置协作者权限管理,开箱即用。
- 📦 开箱即用 - 完整的组织架构数据模型(企业、部门、员工、角色、权限)
- 🚀 高性能 - 多级缓存优化(静态缓存 + Redis + 上下文缓存)
- 🌳 树形结构 - 部门物化路径(Materialized Path),高效子树查询
- 🔒 数据隔离 - 企业级 / 用户级两种隔离方式,自动过滤
- 👥 协作者 - 支持任意资源类型的协作权限管理
- 🔐 权限系统 - 完整的 RBAC + 注解权限(切面自动校验)
- 🔧 易扩展 - 模型可重写,配置灵活,低耦合
composer require hyperf-plus/corpphp bin/hyperf.php vendor:publish hyperf-plus/corpphp bin/hyperf.php migrate// config/autoload/middlewares.php
return [
'http' => [
\HPlus\Corp\Middleware\CorpContextMiddleware::class,
],
];use HPlus\Corp\Model\Corp;
use HPlus\Corp\Model\Department;
use HPlus\Corp\Model\Employee;
use HPlus\Corp\Model\Role;
// 创建企业
$corp = Corp::create([
'name' => '测试企业',
'corp_code' => 'test001',
]);
// 创建部门
$dept = Department::create([
'corp_id' => $corp->corp_id,
'name' => '技术部',
'parent_id' => 0,
]);
// 创建员工
$employee = Employee::create([
'corp_id' => $corp->corp_id,
'department_id' => $dept->department_id,
'name' => '张三',
'mobile' => '13800138000',
]);
// 创建角色
$role = Role::create([
'corp_id' => $corp->corp_id,
'role_name' => '管理员',
'auth_range' => Role::AUTH_RANGE_ALL,
]);| Trait | 隔离维度 | 适用场景 | 过滤逻辑 |
|---|---|---|---|
HasCorpScope |
企业级 | 通知、配置、日志等 | WHERE corp_id = ? |
HasDataScope |
用户级 | 业务数据(订单、话术等) | corp_id + 角色数据范围 + 协作者权限 |
适用于企业内所有人都可见的数据:
use HPlus\Corp\Model\Concern\HasCorpScope;
class Notification extends Model
{
use HasCorpScope;
}
// 查询自动过滤当前企业
$notifications = Notification::query()->get();
// 跳过过滤
Notification::withoutCorpScope()->get();
// 指定企业查询
Notification::ofCorp($corpId)->get();基于角色数据范围自动过滤,支持协作者权限:
use HPlus\Corp\Model\Concern\HasDataScope;
class Order extends Model
{
use HasDataScope;
protected array $fillable = ['corp_id', 'employee_id', 'department_id', ...];
}
// 自动根据角色 auth_range 过滤:
// - 1: 仅本人 → WHERE employee_id = 当前员工
// - 2: 本部门 → WHERE department_id = 当前部门
// - 3: 本部门及下属 → WHERE department_id IN (部门及子部门)
// - 4: 全部 → 不额外过滤
$orders = Order::query()->get(); // 自动过滤
// 创建时自动注入上下文字段
Order::create(['amount' => 100]); // 自动填充 corp_id、employee_id、department_id支持协作者的资源,用户可见数据 = 角色数据范围 ∪ 被授权协作的数据:
use HPlus\Corp\Model\Concern\HasDataScope;
use HPlus\Corp\Model\Collaborator;
class Script extends Model
{
use HasDataScope;
// 启用协作者
protected bool $enableCollaborator = true;
// 资源类型(自定义整数)
protected int $resourceType = 10;
// 资源ID字段(默认主键)
protected string $resourceIdColumn = 'id';
// 创建时自动将创建者添加为协作者(默认 true)
protected bool $autoAddCreatorAsCollaborator = true;
}
// 查询:返回"角色权限内的" + "被授权协作的"
$scripts = Script::query()->get();
// 协作者管理
$script->addCollaborator(userId: 1, scope: Collaborator::SCOPE_EDIT);
$script->removeCollaborator(userId: 1);
$script->setCollaborators([1, 2, 3]);
$script->getCollaboratorIds();
// 检查权限
$script->hasCollaboratorPermission(userId: 1);
$script->currentUserHasCollaboratorPermission();资源类型常量(可自定义任意整数):
Collaborator::RESOURCE_TYPE_CORP = 1; // 企业
Collaborator::RESOURCE_TYPE_AGENT = 2; // 代理商
Collaborator::RESOURCE_TYPE_SCRIPT = 10; // 话术
Collaborator::RESOURCE_TYPE_LINE = 11; // 线路
Collaborator::RESOURCE_TYPE_TASK = 12; // 任务直接使用 Collaborator 模型:
use HPlus\Corp\Model\Collaborator;
// 添加协作者
Collaborator::addCollaborator($userId, $resourceId, $resourceType);
// 移除协作者
Collaborator::removeCollaborator($userId, $resourceId, $resourceType);
// 检查权限
Collaborator::hasPermission($userId, $resourceId, $resourceType);
// 获取用户可访问的资源ID(带缓存)
$ids = Collaborator::getUserResourceIds($userId, $resourceType);
// 批量设置协作者
Collaborator::setResourceCollaborators($resourceId, $resourceType, $userIds);use HPlus\Corp\Context\CorpContext;
// 批量设置
CorpContext::set(
corpId: 1,
employeeId: 100,
departmentId: 10,
authRange: 3,
isAdmin: false
);
// 单独设置/获取
CorpContext::setCorpId(1);
CorpContext::getCorpId();
CorpContext::setEmployeeId(100);
CorpContext::getEmployeeId();
CorpContext::setAuthRange(3);
CorpContext::getAuthRange();
CorpContext::setIsAdmin(true);
CorpContext::isAdmin();
// 临时跳过数据范围过滤
CorpContext::withoutDataScope(function () {
return Order::query()->get();
});use HPlus\Corp\Annotation\Permission;
class UserController
{
#[Permission('user.create')]
public function create() {}
#[Permission('user.edit')]
public function update() {}
// 多个权限满足任一即可
#[Permission('user.delete,admin')]
public function delete() {}
}
// 类级别注解(整个控制器生效)
#[Permission('user')]
class UserController
{
public function list() {} // 需要 user 权限
}特性:
- ✅ 启动时自动收集注解,运行时切面校验,无需额外中间件
- ✅ 管理员(
CorpContext::isAdmin() = true)自动跳过 - ✅ 权限不足抛出
PermissionDeniedException(403)
// 员工模型方法
$employee->hasPermission('user:create');
$employee->hasRole('admin');
// 权限服务
$permissionService = make(PermissionService::class);
$permissionService->hasPermission($employeeId, 'user:create');
$permissionService->setRolePermissions($roleId, [1, 2, 3]);支持用户重写模型,在配置文件中指定自定义模型类:
// config/autoload/corp.php
return [
'models' => [
'corp' => \App\Model\Corp::class,
'employee' => \App\Model\Employee::class,
'collaborator' => \App\Model\Collaborator::class,
],
];自定义模型继承基础模型即可:
namespace App\Model;
use HPlus\Corp\Model\Employee as BaseEmployee;
class Employee extends BaseEmployee
{
protected array $fillable = [
...parent::$fillable,
'wechat_openid',
'ding_id',
];
// 添加自定义关联
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
}通过 CorpManager 获取配置的模型类:
use HPlus\Corp\CorpManager;
$employeeClass = CorpManager::employeeModel();
$employee = $employeeClass::find(1);员工支持加入多个部门,主部门只有一个:
// 设置主部门(自动加入部门列表)
$employee->setPrimaryDepartment($deptId);
// 添加到部门
$employee->addToDepartment($deptId);
// 从部门移除
$employee->removeFromDepartment($deptId);
// 获取所有部门ID
$ids = $employee->getAllDepartmentIds();
// 批量设置部门
$employeeService = make(EmployeeService::class);
$employeeService->setDepartments($employeeId, [1, 2, 3], primaryDepartmentId: 1);| 缓存类型 | 层级 | 有效期 | 用途 |
|---|---|---|---|
| 静态缓存 | 进程级 | 单次请求 | 协作者ID列表、部门子树、字段检测 |
| Redis 缓存 | 分布式 | 5分钟 | 协作者ID列表 |
| 上下文缓存 | 请求级 | 单次请求 | 部门ID列表 |
| 模型缓存 | Hyperf 原生 | 可配置 | 模型数据 |
// 使用模型缓存
$corp = Corp::findFromCache($corpId);
$employees = Employee::findManyFromCache([1, 2, 3]);- ✅ 优先使用
IN查询而非子查询 - ✅ 字段检测优先检查
fillable,避免查库 - ✅ 部门子树使用物化路径(
full_path)高效查询 - ✅ 协作者权限合并到主查询,避免多次查询
corp_id,name,corp_code,status,icon_url,desc等
department_id,corp_id,name,parent_id,full_path,level,order,supervisor_id,employee_count等- 支持树形结构,使用物化路径(Materialized Path)
employee_id,corp_id,department_id,department_ids(JSON),name,mobile,email,status,is_admin等- 支持多部门(主部门 + 兼职部门)
role_id,corp_id,role_name,slug,auth_range(数据权限范围),status等auth_range: 1-仅本人, 2-本部门, 3-本部门及下属, 4-全部
permission_id,name,slug,parent_id,app_code,order等- 支持树形结构
id,user_id,resource_id,resource_type,scopes,status等- 支持任意资源类型的协作权限
class Notification extends Model
{
use HasCorpScope; // 仅企业隔离
}class Order extends Model
{
use HasDataScope; // 企业 + 角色数据范围
}class Script extends Model
{
use HasDataScope;
protected bool $enableCollaborator = true;
protected int $resourceType = 10;
}配合 hyperf-plus/route + hyperf-plus/validate 使用,提供低代码的增删改查能力。
use HPlus\Corp\Crud\CrudService;
class OrderService extends CrudService
{
protected string $model = Order::class;
// 可搜索字段(模糊匹配,支持关联如 customer.name)
protected array $searchable = ['order_no', 'customer.name'];
// 可过滤字段(精确匹配)
protected array $filterable = ['status', 'type', 'department_id'];
// 可排序 / 默认排序 / 默认关联
protected array $sortable = ['created_at', 'amount'];
protected array $defaultSort = ['created_at' => 'desc'];
protected array $with = ['customer'];
// 钩子方法
protected function beforeCreate(array $data): array
{
$data['order_no'] = $this->generateOrderNo();
return $data;
}
protected function beforeDelete(Model $model): bool
{
return $model->status !== Order::STATUS_PAID;
}
// 数据转换
protected function transform(Model $model): array
{
return [...$model->toArray(), 'status_text' => Order::STATUS_MAP[$model->status] ?? ''];
}
}use HPlus\Route\Annotation\ApiController;
use HPlus\Route\Annotation\GetApi;
use HPlus\Route\Annotation\PostApi;
use HPlus\Validate\Annotations\RequestValidation;
use HPlus\Corp\Annotation\Permission;
use HPlus\Corp\Crud\Traits\HasCrud;
#[ApiController(prefix: '/api/orders')]
class OrderController
{
use HasCrud;
protected string $service = OrderService::class;
#[GetApi]
#[Permission('order.list')]
public function list() { return $this->handleList(); }
#[GetApi(path: '/{id:\d+}')]
#[Permission('order.detail')]
public function detail(int $id) { return $this->handleDetail($id); }
#[PostApi]
#[Permission('order.create')]
#[RequestValidation(rules: [
'customer_id' => 'required|integer|exists:customers,id',
'items' => 'required|array|min:1',
'items.*.product_id' => 'required|integer',
], messages: ['customer_id.required' => '请选择客户'])]
public function create() { return $this->handleCreate(); }
#[PostApi(path: '/{id:\d+}')]
#[Permission('order.update')]
#[RequestValidation(rules: ['status' => 'required|integer|in:1,2,3'])]
public function update(int $id) { return $this->handleUpdate($id); }
#[PostApi(path: '/{id:\d+}/delete')]
#[Permission('order.delete')]
public function delete(int $id) { return $this->handleDelete($id); }
#[PostApi(path: '/batch-delete')]
#[Permission('order.delete')]
#[RequestValidation(rules: ['ids' => 'required|array|min:1'])]
public function batchDelete() { return $this->handleBatchDelete(); }
}| 方法 | 说明 |
|---|---|
handleList() |
列表(分页、搜索、过滤、排序) |
handleAll() |
全部(不分页) |
handleDetail($id) |
详情 |
handleCreate() |
创建 |
handleUpdate($id) |
更新 |
handleDelete($id) |
删除 |
handleBatchDelete() |
批量删除 |
handleUpdateStatus($id) |
更新状态 |
handleBatchUpdateStatus() |
批量更新状态 |
$service = make(OrderService::class);
// 查询
$result = $service->list(['keyword' => '关键词', 'status' => 1, 'page' => 1]);
$items = $service->all(['status' => 1]);
$detail = $service->detail($id);
$model = $service->find($id);
$model = $service->findBy(['order_no' => 'ORD001']);
// 写入
$model = $service->create(['customer_id' => 1]);
$model = $service->update($id, ['status' => 2]);
$service->delete($id);
$service->batchDelete([1, 2, 3]);
$service->updateStatus($id, 1);
$service->batchUpdateStatus([1, 2, 3], 0);组织架构变更自动触发事件,支持监听扩展:
use HPlus\Corp\Event\EmployeeEvent;
use HPlus\Corp\Event\DepartmentEvent;
use HPlus\Corp\Event\RoleEvent;
// 监听员工角色变更
Event::listen(EmployeeEvent::ROLE_CHANGED, function (EmployeeEvent $event) {
// $event->employeeId
// $event->oldRoleIds
// $event->newRoleIds
});
// 监听部门变更
Event::listen(DepartmentEvent::CREATED, function (DepartmentEvent $event) {
// $event->departmentId
// $event->data
});欢迎提交 Issue 和 Pull Request!
MIT