use ZhiyiPlusModelsRole; use ZhiyiPlusServicesUserAbility;
trait UserHasAbility {
/*** Abiliry service instance.** @var \Zhiyi\Plus\Services\UserAbility*/
protected $ability;/*** User ability.** @param array $parameters* ability();* ability($ability);* ability($role, $ability);* @return mixed* @author Seven Du <shiweidu@outlook.com>*/
public function ability(...$parameters)
{if (isset($parameters[1])) {return ($role = $this->resolveAbility()->roels($parameters[0]))? $role->ability($parameters[1]): false;} elseif (isset($parameters[0])) {return $this->resolveAbility()->all($parameters[0]);}return $this->resolveAbility();
}/*** The user all roles.** @param string $role* @return mied* @author Seven Du <shiweidu@outlook.com>*/
public function roles(string $role = '')
{if ($role) {return $this->ability()->roles($role);}return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
}/*** Resolve ability service.** @return \Zhiyi\Plus\Services\UserAbility* @author Seven Du <shiweidu@outlook.com>*/
protected function resolveAbility()
{if (! ($this->ability instanceof UserAbility)) {$this->ability = new UserAbility();}return $this->ability->setUser($this);
}
} Ability 實例
<?php namespace ZhiyiPlusServices; use IlluminateSupportCollection; use ZhiyiPlusModelsUser as UserModel; use ZhiyiPlusContractsModelUserAbility as UserAbilityContract;
class UserAbility implements UserAbilityContract {
protected $user;/*** Get all roles or get first role.** @param string $role* @return mixed* @author Seven Du <shiweidu@outlook.com>*/
public function roles(string $role = '')
{$roles = $this->user()->roles()->get()->keyBy('name');if (! $role) {return $roles;}return $roles->get($role, false);
}
/*** Get all abilities or get first ability.** @param string $ability* @return mixed* @author Seven Du <shiweidu@outlook.com>*/
public function all(string $ability = '')
{$roles = $this->roles();$roles->load('abilities');$abilities = $roles->reduce(function ($collect, $role) {return $collect->merge($role->abilities->keyBy('name'));}, new Collection());if (! $ability) {return $abilities;}return $abilities->get($ability, false);
}
/*** Get user instance.** @return \Zhiyi\Plus\Models\User* @author Seven Du <shiweidu@outlook.com>*/
public function user(): UserModel
{return $this->user;
}
/*** Set user model.** @param \Zhiyi\Plus\Models\User $user* @author Seven Du <shiweidu@outlook.com>*/
public function setUser(UserModel $user)
{$this->user = $user;return $this;
}
} Role 模型所需代碼
<?php namespace ZhiyiPlusModels; use IlluminateDatabaseEloquentModel;
class Role extends Model {
/*** Get all abilities of the role.** @return \Illuminate\Database\Eloquent\Relations\BelongsToMany* @author Seven Du <shiweidu@outlook.com>*/
public function abilities()
{return $this->belongsToMany(Ability::class, 'ability_role', 'role_id', 'ability_id');
}
/*** Get or check The role ability.** @param string $ability* @return false|\User\Plus\Models\Ability* @author Seven Du <shiweidu@outlook.com>*/
public function ability(string $ability)
{return $this->abilities->keyBy('name')->get($ability, false);
}
} 使用
然后我們打開 User 模型wen jia文件添加如下代碼:
class User ... {
use UserHasAbility;
} 總結
其實性狀在 User 模型中只暴露了 roles 和 ability 兩個公開方法。但是已經足以勝任用戶組權限判斷邏輯了。
整個 ability 都是結合在集合之上的一些封裝,這樣是的代碼調用更加優雅。
以上代碼是在開發ThinkSNS+中的實際真實代碼。具體的實現可參考項目。
以上代碼都來自于ThinkSNS Plus,看完整的開發代碼可以看倉庫:
GitHub: https://github.com/slimkit/thinksns-plus (開源不易,求 Star )