Laravel conditionally add global scopes after method boot

好久不见. 提交于 2021-01-29 06:50:15

问题


Is it possible to add a global scope after the model has already passed the constructor?

I would like to catch an event (for example creating) and attach a global scope only if the model is creating.

So far I've done:

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

The scope constructor is called, but the apply method from it is never fired because the model at that point already obviously passed the part where it fires the scopes. How could I manually fire it?


回答1:


tl;dr; It is not possible. At the time when the Eloquent events are firing scopes are already loaded and applied.

Use case: I wanted to add additional scopes on model create/edit/delete to be able to do some sort of dynamic authorization, however this is not valid because Laravel uses Eloquent query builder for doing DB SELECT. For everything else, such as inserts or deletes, a different query is formed and is not connected to a given query builder, so even if you could tap into it, it makes no sense to do it as it would form a separate query for create/edit/delete actions anyways.

What I ended up doing was reusing the logic which I used within scopes, but instead of limiting the query initially (what scopes do), I would do my checks within event listener and return true/false depending on that check.

For this concrete example, returning false upon catching eloquent.creating event would mean that the model will not be created, which is exactly what I needed.

For any more details, feel free to check authorization package for microservices I developed using this approach.



来源:https://stackoverflow.com/questions/63052784/laravel-conditionally-add-global-scopes-after-method-boot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!