我开始开发SaaS应用程序,并且已经创建了我的数据库结构。我打算创建一个中间件文件来处理该请求的数据库连接。在这个中间件文件中,我想创建一个模型,它总是只选择与当前连接cust_id
(外键)对应的任何表中的行。
例如:
$Customers->where('cust_id', $cust_id)->first();
如何在不必在每个select语句中指定where('cust_id', $cust_id)
的情况下执行此操作?
答案 0 :(得分:2)
您可以使用模型中的 Eloquent全局查询范围轻松实现这一目标。您可以在此处详细了解它们:http://laravel.com/docs/5.1/eloquent#query-scopes
首先,您需要定义多租户范围类,它将更新所有运行的查询并在 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 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();
请注意,我还没有测试过这些确切的代码,如果您发现任何问题,请告诉我们,我们非常乐意为您提供相应的服务:)