larvel -5和多租户数据库设置


Laravel-5 and Multitenancy database setup

我开始开发一个SaaS应用程序,并且已经创建了我的数据库结构。我计划创建一个中间件文件来处理该请求的数据库连接。在这个中间件文件中,我想创建一个模型,它将始终只选择与当前连接cust_id(外键)对应的任何表中的行。

例如:

$Customers->where('cust_id', $cust_id)->first();

我如何做到这一点,而不必在每个选择语句中指定where('cust_id', $cust_id) ?

您可以在您的模型中使用Eloquent的全局查询范围轻松实现这一点。你可以在这里阅读更多关于他们的信息:http://laravel.com/docs/5.1/eloquent#query-scopes

首先,您需要定义Multitenant作用域类,它将更新运行的所有查询并在cust_id字段上添加约束:
class MultitenantScope implements ScopeInterface
{
  public function apply(Builder $builder, Model $model)
  {
    if (Auth::id()) {
      $builder->whereCustId(Auth::id()); 
    } else {
      $model = $builder->getModel();
      // apply a constraint that will never be true
      // so that no records are fetched for unauthorized users
      $builder->whereNull($model->getKeyName()); 
    }
 }
  public function remove(Builder $builder, Model $model)
  {
    $query = $builder->getQuery();
    $query->wheres = collect($query->wheres)->reject(function ($where) {
      return ($where['column'] == 'cust_id');
    })->values()->all();
  }  
}

然后你需要一个trait,你将添加到需要被过滤的模型中:

trait MultitenantTrait
{
  public static function bootMultitenantTrait()
  {
    static::addGlobalScope(new MultitenantScope());
  }
  public static function allTenants()
  {
    return (new static())->newQueryWithoutScope(new MultitenantScope());
  }
}

最后一部分是将MultitenantTrait添加到您的模型:

class SomeModel extends Eloquent {
  use MultitenantTrait;
}

现在,每次使用Eloquent的模型方法执行任何查询时,cust_id约束将应用于查询,并且只有属于给定cust_id的模型才可用。

如果出于某种原因需要访问所有对象,可以使用allTenants()方法来运行查询,而不需要附加约束:

$allRows = SomeModel::allTenants()->get();

请记住,我还没有测试过确切的代码,所以让我知道,如果你看到任何问题,我会很高兴为你工作:)