使用示例
在代碼中使用數據權限、目前支持多種方式進行動態開啓與關閉。 以下舉幾種常見的開發案例
對整個模型進行數據權限控制
以默認的 User
模型為例,假設我們需要對 User
模型進行數據權限控制。
可以在 User
模型中 use DataScopes
trait 來啓用數據權限作用域。
php
use App\Library\DataPermission\Scope\DataScopes;
class User {}
// 使用數據權限作用域
use DataScopes;
// 其他代碼...
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
這樣會使所有對 User
模型的查詢都自動應用數據權限控制。
對某個代碼塊進行數據權限控制
得益於 Hyperf Aop 特性,我們可以在類或者類方法上使用 DataScope 註解來對指定的代碼塊開啓數據權限控制。
以自帶的用户模塊的分頁列表為例
php
class UserService
{
#[DataScope(
scopeType: ScopeType::CREATED_BY,
onlyTables: ['user']
)]
public function page(array $params, int $page = 1, int $pageSize = 10): array
{
return parent::page($params, $page, $pageSize); // TODO: Change the autogenerated stub
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
這樣在調用 page
方法時,數據權限會自動應用到查詢中。
對指定的 ORM Query 進行權限控制
在某些特定場景中,需要更加細化的進行權限隔離。此時可以通過 Factory::make()->build()
方法來對指定的 Query 進行限制
php
use App\Library\DataPermission\Factory;
use App\Model\Permission\User;
use App\Model\Permission\Wallet;
class DemoService {
public function test(User $user): void{
$walletQuery = Wallet::query();
// 對 WalletQuery 單獨進行數據隔離拼接
Factory::make()->build($user,$walletQuery->getQuery());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
指定其他字段作為隔離條件
在某些情況下,業務表中可能會與默認的 created_by
dept_id
字段名稱不一致,或者在某些複雜 join 查詢中。表名經過 table as xxxx
類似的操作。這個時候就需要指定新的隔離字段了。以下舉幾個例子方便理解在不同的使用方法中如何指定新的字段
在使用註解隔離某個方法的時候
自帶的 DataScope
註解有一些參數可以很方便的我們指定新的字段
php
<?php
declare(strict_types=1);
/**
* This file is part of MineAdmin.
*
* @link https://www.mineadmin.com
* @document https://doc.mineadmin.com
* @contact root@imoi.cn
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
*/
namespace App\Library\DataPermission\Attribute;
use App\Library\DataPermission\ScopeType;
use Hyperf\Di\Annotation\AbstractAnnotation;
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
final class DataScope extends AbstractAnnotation
{
public function __construct(
// 指定部門字段名稱
private readonly string $deptColumn = 'dept_id',
// 創建人字段名稱
private readonly string $createdByColumn = 'created_by',
// 隔離方式
private readonly ScopeType $scopeType = ScopeType::DEPT_CREATED_BY,
// 只對指定的表進行隔離。為空則全部隔離
private readonly ?array $onlyTables = null
) {}
public function getOnlyTables(): ?array
{
return $this->onlyTables;
}
public function getDeptColumn(): string
{
return $this->deptColumn;
}
public function getCreatedByColumn(): string
{
return $this->createdByColumn;
}
public function getScopeType(): ScopeType
{
return $this->scopeType;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
在手動使用 Factory::make()->build
時
而在手動調用 Factory
實例進行條件拼接的時候。就需要使用 App\Library\DataPermission\Context
來進行配置了。
php
use App\Library\DataPermission\Context as Ctx;
use App\Library\DataPermission\Factory;
// 只對 sss 表進行數據隔離
Ctx::setOnlyTables(['sss']);
// 設置部門字段名稱
Ctx::setDeptColumn('department_id');
// 設置創建人字段名稱
Ctx::setCreatedByColumn('creator');
// 設置隔離方式
Ctx::setScopeType(ScopeType::DEPT_CREATED_BY);
$query = XXXModel::query();
Factory::make()->build($user,$query->getQuery());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WARNING
需要注意,不管哪種使用方式。如果新開一個協程。都要重新設置一遍才能起效