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

5.0.0 2017-01-29 20:41 UTC

README

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

Teamwork 是为您的 Laravel 5 项目添加用户/团队关联以及邀请的最快、最简单的方法。

内容

安装

对于 Laravel 5.4

"mpociot/teamwork": "~5.0"

对于 Laravel 5.3

"mpociot/teamwork": "~4.0"

对于 Laravel 5.2

"mpociot/teamwork": "~3.0"

对于 Laravel 5.0 / 5.1

"mpociot/teamwork": "~2.0"

将所需版本添加到您的 composer.json。然后运行 composer installcomposer update

(或运行 composer require mpociot/teamwork 如果您更喜欢这种方式)

然后,在您的 config/app.php 中添加

Mpociot\Teamwork\TeamworkServiceProvider::class,

providers 数组。

Teamwork Facade 将在 Service Provider 中自动安装。

配置

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

模型

团队

app/Team.php 中使用以下示例创建一个 Team 模型

<?php namespace App;

use Mpociot\Teamwork\TeamworkTeam;

class Team extends TeamworkTeam
{
}

Team 模型有两个主要属性

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

owner_id 是一个可选属性,在数据库中可以设置为 NULL。

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

用户

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 autoload

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');

现在只有当认证用户是当前团队的拥有者时,才能访问该路由。

此中间件旨在保护只有团队拥有者才能编辑/创建/删除该模型的路由。

现在您已准备就绪。

用法

脚手架

通过使用 make:teamwork 命令,您可以轻松地为新的 Laravel 项目添加团队功能。

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() — 返回与拥有此团队的 User 模型的单对一关系。
  • 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作为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中添加您的监听器

/**
 * 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 teams for the currently active team of the authenticated user
Task::all();

// gets all tasks from all teams globally
Task::allTeams()->get();

许可协议

Teamwork 是免费软件,根据 MIT 许可协议分发。

'Marvel Avengers' 图片根据 Creative Commons 2.0 许可,图片来自 W_Minshull