Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.x] Add hasScope function to the Base Model #32622

Merged
merged 7 commits into from
May 1, 2020
Merged

[7.x] Add hasScope function to the Base Model #32622

merged 7 commits into from
May 1, 2020

Conversation

alexbowers
Copy link
Contributor

This hasScope method cleans up checking if a scope exists in a dynamic way.

The use case for this is requests containing an array of filters to be applied (via scopes), the code is more expressive with:

public function index(Request $request)
    {
        $post = Post::query();

        foreach ($request->get('filters', []) as $filter) {
            if ($post->hasScope($filter)) {
                $post->{$filter}();
            }
        }

        return $post->paginate();
    }

@alexbowers
Copy link
Contributor Author

Closes laravel/ideas#2192

@alexbowers
Copy link
Contributor Author

The test that is failing seems to have no bearing on the code i've written. It also does not fail for me locally, any ideas?

@driesvints
Copy link
Member

@alexbowers tests on 7.x were temporarily failing but are fixed. Can you rebase?

@alexbowers
Copy link
Contributor Author

@driesvints Done

@koenhoeijmakers
Copy link
Contributor

I don't really see the use case for a hasScope method but i'm not against it because there probably are reasons for it.

But i don't think your use case is correct and its even dangerous, letting the client decide which scopes are sent via your filters input opens up issues where somebody can register any scope.

For example: a scope scopeAdmin that allows the you to see every single Post instead of only those who are visible. Sending filters[admin] now opens up every post.

@alexbowers
Copy link
Contributor Author

alexbowers commented May 1, 2020

@koenhoeijmakers That can easily be controlled with a whitelist / blacklist. My use case is not an open API, but an internal one, which will make it cleaner than having a switch statement for my scopes.

Also, your access to data should already be restricted as a user as part of a Policy / default scope being applied, all that applying any additional scopes would do is further restrict the data.

For example,

If you are User 1 and you are trying to get all your posts there would by default on the controller be a restriction:

$post = Post::byAuthor(auth()->id);

or similar which would be restricting the posts to the current user, adding a filters[admin] to that would still have your original scope applied.

@n10000k
Copy link

n10000k commented May 1, 2020

Create a macro.

@GrahamCampbell
Copy link
Member

Create a macro.

I don't agree here. To me, the main benefit of this PR seems to be separation of concerns. Models now decide if they have a scope, rather than reflection by an outsider.

@@ -1373,8 +1384,8 @@ public function __call($method, $parameters)
return call_user_func_array(static::$macros[$method], $parameters);
}

if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) {
return $this->callScope([$this->model, $scope], $parameters);
if ($this->hasScope($method)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda odd that hasScope expects the scope name and not the method name, but callScope expects the actual method name. (don't change anything yet please. I am writing this comment to be discussed)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did find that weird, but wanted to change the minimum amount possible, and since changing how callScope works would be considered a breaking change, wanted to delegate that to a future PR (if desired).

@taylorotwell taylorotwell merged commit b706fe6 into laravel:7.x May 1, 2020
@alexbowers
Copy link
Contributor Author

Thanks for the merge Taylor,

Any thoughts on Grahams Comment #32622 (comment) ?

@alexbowers alexbowers deleted the feature/has-scope branch May 1, 2020 15:49
@GrahamCampbell
Copy link
Member

I think we should change it in Laravel 8. I'll send a PR.

@driesvints
Copy link
Member

This hasn't been released yet so you can pr to 7.x

@alexbowers
Copy link
Contributor Author

@driesvints The change Graham is on about is already released, its changing the method signature of callScope to not be callable and to to build the callable instance itself.

@GrahamCampbell
Copy link
Member

Actually, I am thinking we can do this non-breaking on 7.x, having looked into the code. We will need another method. Not possible to change the old method because a scope could have the same name as a global function which is callable.,

@GrahamCampbell
Copy link
Member

#32631

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants