Laravel 在方法启动后有条件地添加全局范围

Posted

技术标签:

【中文标题】Laravel 在方法启动后有条件地添加全局范围【英文标题】:Laravel conditionally add global scopes after method boot 【发布时间】:2020-11-13 02:13:26 【问题描述】:

模型已经通过构造函数后,是否可以添加全局作用域?

我想捕捉一个事件(例如creating)并仅在模型正在创建时附加一个全局范围。

到目前为止,我已经完成了:

Event::listen('eloquent.creating*', function ($event, $model) 
    /**
     * @var Model $eloquentModel
     */
    $eloquentModel = $model[0];
    $eloquentModel->addGlobalScope(new AuthorizationScope($event));
);

作用域构造函数被调用,但其中的apply 方法从未被触发,因为此时模型显然已经通过了它触发作用域的部分。我怎么能手动触发它?

【问题讨论】:

你想用这个实现什么?如果我有一个具体的用例,我可能会想另一种方法来做到这一点。 我有一个包可以根据一些输入组装查询。我在范围内使用这些来限制查询的输出。我希望在创建/更新/删除时也能发挥同样的作用。 它在文档中说您需要首先在模型类上启用模型事件才能获取模型事件。是你做的吗? laravel.com/docs/7.x/eloquent#events Laravel 会独立触发这些事件,无论它们是否启用。 “启用”仅使您能够将该事件重定向到您选择的事件类。这部分确实有效,我完美地捕捉到了事件。我实际上找到了一个替代方案,将在下面发布。 【参考方案1】:

tl;博士;这不可能。在 Eloquent 事件触发时,作用域已经加载并应用了。

用例:我想在模型创建/编辑/删除上添加额外的范围,以便能够进行某种动态授权,但这无效,因为 Laravel 使用 Eloquent 查询构建器来执行 DB SELECT。对于其他所有内容,例如插入或删除,会形成一个不同的查询并且不连接到给定的查询构建器,因此即使您可以利用它,这样做也没有任何意义,因为它会形成一个单独的查询创建无论如何/编辑/删除操作。

我最终做的是重用我在范围内使用的逻辑,但不是最初限制查询(范围做什么),而是在事件侦听器中进行检查并返回 true/false,具体取决于那张支票。

对于这个具体的例子,在捕捉到eloquent.creating 事件时返回false 意味着不会创建模型,这正是我所需要的。

有关更多详细信息,请随时查看我使用此方法开发的authorization package for microservices。

【讨论】:

以上是关于Laravel 在方法启动后有条件地添加全局范围的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 5.5 中根据用户角色应用全局范围

获取查询后有条件地执行 graphql 突变

检查变量是不是设置在全局范围内?

Laravel 全局范围认证

如何定义常量在全局范围内nodejs

没有全局范围的 Laravel 身份验证