oliuz / teamwork
用于 Laravel 框架的用户/团队关联
Requires
- php: ^7.4|^8.0.2
- laravel/framework: ^8.0|^9.0
Requires (Dev)
- illuminate/database: ^8.0|^9.0
- mockery/mockery: ^1.0
- orchestra/testbench: ^6.0|^7.0
- phpunit/phpunit: ^8.0|^9.0
README
Teamwork 是向您的 Laravel 项目中添加用户/团队关联以及邀请的最快、最简单的方法。
内容
安装
适用于 Laravel ^8.0|^9.0
"oliuz/teamwork": "^9.0"
将您需要的版本添加到 composer.json。然后运行 composer install
或 composer update
。
(或者如果您愿意,可以运行 composer require oliuz/teamwork
)
在服务提供者中会自动安装 Teamwork
Facade。
配置
要发布 Teamwork 的配置和迁移文件,请运行 vendor:publish
命令。
php artisan vendor:publish --provider="Mpociot\Teamwork\TeamworkServiceProvider"
这将在您的配置目录中创建一个 teamwork.php
文件。默认配置应该可以满足您的需求,但如果您想自定义 Teamwork 将使用的表/模型名称,可以查看它。
用户与团队的关联
运行 migration
命令,以生成 Teamwork 所需的所有表。如果您的用户存储在除了 users
之外的表中,请务必修改已发布的迁移。
php artisan migrate
迁移后,将创建 3 个新表
- teams — 存储团队记录
- team_user — 存储用户和团队之间的多对多关系
- team_invites — 存储待处理的电子邮件地址到团队的邀请
您还会注意到,在您的用户表中已添加了一个新的列 current_team_id
。此列将定义当前用户被分配到的团队。
模型
用户
将 UserHasTeams
特性添加到您现有的用户模型中
<?php namespace App; use Mpociot\Teamwork\Traits\UserHasTeams; class User extends Model { use UserHasTeams; // Add this trait to your model }
这将启用与 Team
的关联,并在您的 User
模型中添加以下方法:teams()
、ownedTeams()
、currentTeam()
、invites()
、isTeamOwner()
、isOwnerOfTeam($team)
、attachTeam($team, $pivotData = [])
、detachTeam($team)
、attachTeams($teams)
、detachTeams($teams)
、switchTeam($team)
、isOwnerAuth()
、isOwnerAuthCheck()
。
不要忘记运行 composer 自动加载
composer dump-autoload
中间件
如果您想使用中间件来保护当前团队的拥有者,只需将中间件提供者添加到您的 app\Http\Kernel.php
文件中。
protected $routeMiddleware = [ ... 'teamowner' => \Mpociot\Teamwork\Middleware\TeamOwner::class, ... ];
之后,您可以在路由文件中使用 teamowner
中间件,如下所示。
Route::get('/owner', function(){ return "Owner of current team."; })->middleware('auth', 'teamowner');
现在,只有当认证用户是当前团队的拥有者时,才能访问该路由。
此中间件旨在保护只有团队拥有者才能编辑/创建/删除该模型的路由。
现在,您就可以开始使用了。
用法
脚手架
为您的 Laravel 新项目添加团队功能最简单的方法是使用 make:teamwork
命令。
php artisan make:teamwork
此命令将创建所有视图、路由、模型和控制器,使您的项目为团队做好准备。
默认情况下,以下部分将为您创建:
- 团队列表
- 团队创建/编辑/删除
- 邀请新成员加入团队
- 团队模型
将其想象成为 Teamwork 定制的 make:auth
命令。
要开始使用,请查看项目中新安装的 /teams
路由。
基本概念
让我们先创建两个不同的团队。
$team = new Team(); $team->owner_id = User::where('username', '=', 'sebastian')->first()->getKey(); $team->name = 'My awesome team'; $team->save(); $myOtherCompany = new Team(); $myOtherCompany->owner_id = User::where('username', '=', 'marcel')->first()->getKey(); $myOtherCompany->name = 'My other awesome team'; $myOtherCompany->save();
现在,由于 UserHasTeams
特性,将团队分配给用户变得非常简单。
$user = User::where('username', '=', 'sebastian')->first(); // team attach alias $user->attachTeam($team, $pivotData); // First parameter can be a Team object, array, or id // or eloquent's original technique $user->teams()->attach($team->id); // id only
通过使用 attachTeam
方法,如果用户没有分配团队,则将自动设置 current_team_id
列表。
了解我的团队
用户当前分配的团队可以通过 currentTeam
关系访问,如下所示:
echo "I'm currently in team: " . Auth::user()->currentTeam->name; echo "The team owner is: " . Auth::user()->currentTeam->owner->username; echo "I also have these teams: "; print_r( Auth::user()->teams ); echo "I am the owner of these teams: "; print_r( Auth::user()->ownedTeams ); echo "My team has " . Auth::user()->currentTeam->users->count() . " users.";
Team
模型可以访问以下方法:
invites()
— 返回与关联邀请的多对多关系。users()
— 返回与该团队关联的所有用户的多对多关系。owner()
— 返回与拥有该团队的用户模型的一对一关系。hasUser(User $user)
— 帮助函数,用于确定用户是否是团队成员。
团队拥有者
如果您需要检查用户是否是团队拥有者(无论当前团队是什么),请使用用户模型上的 isTeamOwner()
方法。
if( Auth::user()->isTeamOwner() ) { echo "I'm a team owner. Please let me pay more."; }
此外,如果您需要检查用户是否是特定团队的拥有者,请使用
$team = Auth::user()->currentTeam; if( Auth::user()->isOwnerOfTeam( $team ) ) { echo "I'm a specific team owner. Please let me pay even more."; }
isOwnerOfTeam
方法还允许将数组或 ID 作为团队参数。
切换当前团队
如果您的用户是多个团队的成员,您可能希望通过某种方式为他们提供访问“切换团队”机制的权利。
这意味着用户有一个“活动”团队,即当前分配给用户的团队。所有其他团队仍然保留在关联中!
很高兴我们有UserHasTeams
特性。
try { Auth::user()->switchTeam( $team_id ); // Or remove a team association at all Auth::user()->switchTeam( null ); } catch( UserNotInTeamException $e ) { // Given team is not allowed for the user }
就像isOwnerOfTeam
方法一样,switchTeam
方法接受团队对象、数组、id或null作为参数。
邀请他人
如果只有你一个人是团队成员,最好的团队也毫无用处。
要邀请其他用户加入您的团队,请使用Teamwork
外观。
Teamwork::inviteToTeam( $email, $team, function( $invite ) { // Send email to user / let them know that they got invited });
您还可以通过提供具有email
属性的对象来发送邀请
$user = Auth::user(); Teamwork::inviteToTeam( $user , $team, function( $invite ) { // Send email to user / let them know that they got invited });
此方法将创建一个TeamInvite
模型,并将其作为可调用的第三个参数返回。
此模型具有以下属性
email
— 被邀请的电子邮件。accept_token
— 用于接受邀请的唯一令牌。deny_token
— 用于拒绝邀请的唯一令牌。
除了这些属性外,该模型还具有以下关系
user()
— 使用email
作为用户模型上的唯一标识符的一对一关系。team()
— 一对一关系返回被邀请的团队。inviter()
— 一对一关系返回创建邀请的用户。
注意: inviteToTeam
方法将不会检查给定的电子邮件是否已有待处理的邀请。要检查待处理的邀请,请使用Teamwork
外观上的hasPendingInvite
方法。
示例用法
if( !Teamwork::hasPendingInvite( $request->email, $request->team) ) { Teamwork::inviteToTeam( $request->email, $request->team, function( $invite ) { // Send email to user }); } else { // Return error - user already invited }
接受邀请
一旦您邀请了其他用户加入您的团队,为了接受邀请,请再次使用Teamwork
外观。
$invite = Teamwork::getInviteFromAcceptToken( $request->token ); // Returns a TeamworkInvite model or null if( $invite ) // valid token found { Teamwork::acceptInvite( $invite ); }
acceptInvite
方法做两件事
- 调用
attachTeam
与邀请团队在当前认证用户上。 - 之后删除邀请。
拒绝邀请
就像接受邀请一样
$invite = Teamwork::getInviteFromDenyToken( $request->token ); // Returns a TeamworkInvite model or null if( $invite ) // valid token found { Teamwork::denyInvite( $invite ); }
denyInvite
方法只负责从数据库中删除邀请。
附加/分离/邀请事件
如果您需要在将团队附加到/从用户中分离或邀请用户后运行其他进程,您可以监听这些事件
\Mpociot\Teamwork\Events\UserJoinedTeam \Mpociot\Teamwork\Events\UserLeftTeam \Mpociot\Teamwork\Events\UserInvitedToTeam
在您的EventServiceProvider
中添加您的监听器
/** * The event listener mappings for the application. * * @var array */ protected $listen = [ ... \Mpociot\Teamwork\Events\UserJoinedTeam::class => [ App\Listeners\YourJoinedTeamListener::class, ], \Mpociot\Teamwork\Events\UserLeftTeam::class => [ App\Listeners\YourLeftTeamListener::class, ], \Mpociot\Teamwork\Events\UserInvitedToTeam::class => [ App\Listeners\YourUserInvitedToTeamListener::class, ], ];
用户加入团队和用户离开团队事件公开用户和团队的ID。在您的监听器中,您可以像这样访问它们
<?php namespace App\Listeners; use Mpociot\Teamwork\Events\UserJoinedTeam; class YourJoinedTeamListener { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param UserJoinedTeam $event * @return void */ public function handle(UserJoinedTeam $event) { // $user = $event->getUser(); // $teamId = $event->getTeamId(); // Do something with the user and team ID. } }
用户被邀请加入团队事件包含一个邀请对象,可以像这样访问
<?php namespace App\Listeners; use Mpociot\Teamwork\Events\UserInvitedToTeam; class YourUserInvitedToTeamListener { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param UserInvitedToTeam $event * @return void */ public function handle(UserInvitedToTeam $event) { // $user = $event->getInvite()->user; // $teamId = $event->getTeamId(); // Do something with the user and team ID. } }
限制模型到当前团队
如果您的模型 somehow限制在当前团队,您将发现自己会反复编写以下查询:Model::where('team_id', auth()->user()->currentTeam->id)->get();
。
为了自动化此过程,您可以让模型使用UsedByTeams
特质。此特质将自动将认证用户的当前团队ID附加到所有查询中,并在保存模型时将其添加到名为team_id
的字段中。
注意
此假设模型有一个名为
team_id
的字段
用法
use Mpociot\Teamwork\Traits\UsedByTeams; class Task extends Model { use UsedByTeams; }
使用此特质时,所有查询都将附加WHERE team_id=CURRENT_TEAM_ID
。如果您的应用程序中存在确实需要检索所有模型,无论它们属于哪个团队的地方,您可以使用allTeams
作用域。
示例
// gets all tasks for the currently active team of the authenticated user Task::all(); // gets all tasks from all teams globally Task::allTeams()->get();
许可证
Teamwork是免费软件,根据MIT许可证的条款分发。
《复仇者联盟》图像根据Creative Commons 2.0许可 - 照片来自W_Minshull