mpociot/teamwork

Laravel 5 框架的用户与团队关联

安装数: 490,974

依赖: 5

建议者: 0

安全: 0

星标: 1,069

关注者: 39

分支: 171

开放问题: 1

9.0.0 2024-06-18 11:45 UTC

README

此包支持 Laravel 6 及以上版本。

Latest Version Software License Build Status codecov.io SensioLabsInsight Scrutinizer Code Quality

Teamwork 是为 Laravel 6+ 项目添加用户/团队关联并带有邀请功能的最快、最简单的方法。

安装

composer require mpociot/teamwork

Teamwork 门面将由 Laravel 自动发现。

配置

要发布 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。此列将定义用户当前分配到的团队。

模型

Team

app/Team.php 中创建一个 Team 模型,如下所示

<?php namespace App;

use Mpociot\Teamwork\TeamworkTeam;

class Team extends TeamworkTeam
{
}

Team 模型有两个主要属性

  • owner_id — 指向拥有此团队的 User 模型的引用。
  • name — 团队的人类可读名称。

owner_id 是一个可选属性,在数据库中可为空。

当扩展 TeamworkTeam 时,请记住在 config/teamwork.php 中将 team_model 变量更改为您的新模型。例如:'team_model' => App\Team::class

User

UserHasTeams 特性添加到您现有的 User 模型中

<?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)

别忘了运行 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 项目添加 Team 功能的最简单方法是使用 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 列。

或者,您还可以使用 UserHasTeams 特性中的 createOwnedTeam 方法。它将为用户创建团队作为所有者,将用户附加到团队并切换到新创建的团队。

// Create user owned team and switch the current team to this new team.
$team = $user->createOwnedTeam(['name' => 'My awesome team']);

// If user has another current team active, you should pass second parameter as true to force switch to the new team.
$team = $user->createOwnedTeam(['name' => 'My awesome team'], true);

该函数将返回您团队模型的新实例。

了解我的团队(们)

用户当前分配的团队可以通过以下方式通过 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() — 返回与拥有此团队的 User 模型的单一对一关系。
  • hasUser(User $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 作为 User 模型上的唯一标识符的单一对一关系。
  • 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 中添加您的监听器(s)

/**
 * 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.
    }
}

将模型限制为当前团队

如果您的模型以某种方式限制在当前团队,您将发现自己会反复编写此查询: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