If domain driven design is the architecture of the application, the controller should use a repository with a method that is the best fit for the controller.
$products=Product::active()->inStock()->when($request->has('category'),function($query)use($request){return$query->inCategory($request->category);})->priceRange($request->price_min,$request->price_max)->sortBy($request->sort)->paginate(20);// can be$products=ProductRepository->getFilteredPage(ProductFiltersDTO::fromRequest($request));
Where statements like active, in stock and pages should be controlled by business logic in the domain.
If the goal is to have reusable local scopes, traits are a better option.
I understand you want to show this Eloquent feature, and that is good.
For me the handling of local scopes shows a problem in the ORM.
Maybe the problem started with naming?
Why are there two ways to recognise scopes?
The hook method, newEloquentBuilder, is confusing.
Using traits shows that there is no mechanism to share local scopes.
A possible way to fix this could be to use the global scopes mechanism and add a defaultScopes property.
Eloquent’s dual approach—local scopes defined as methods (using the “scope” prefix) and global scopes applied automatically—can be confusing since developers must remember two distinct methods to achieve similar filtering. Although traits can be used to share local scopes across models, there’s no built-in mechanism to share them without code duplication. Proposals like introducing a defaultScopes property could streamline default filtering, but this may reduce the flexibility developers currently enjoy when customizing queries.
I did an initial rework of the scopes a few days ago.
I dismissed the idea of building on top of the current scopes very quickly because it is so ingrained in how Eloquent works at the moment.
The problem with my solution is that it isn't possible to use closures in attributes, that is a feature of the global scope. So we have to wait for php 8.5 to make that possible.
If domain driven design is the architecture of the application, the controller should use a repository with a method that is the best fit for the controller.
Where statements like active, in stock and pages should be controlled by business logic in the domain.
If the goal is to have reusable local scopes, traits are a better option.
This way it is possible to connect the local scope to multiple models like a global scope.
While the
Builderclass is well intentioned it doesn't solve any problems, it only adds more abstraction.I mostly use Traits, however, I wrote this blog to show that we can make custom builders
I understand you want to show this Eloquent feature, and that is good.
For me the handling of local scopes shows a problem in the ORM.
Maybe the problem started with naming?
Why are there two ways to recognise scopes?
The hook method,
newEloquentBuilder, is confusing.Using traits shows that there is no mechanism to share local scopes.
A possible way to fix this could be to use the global scopes mechanism and add a
defaultScopesproperty.Eloquent’s dual approach—local scopes defined as methods (using the “scope” prefix) and global scopes applied automatically—can be confusing since developers must remember two distinct methods to achieve similar filtering. Although traits can be used to share local scopes across models, there’s no built-in mechanism to share them without code duplication. Proposals like introducing a defaultScopes property could streamline default filtering, but this may reduce the flexibility developers currently enjoy when customizing queries.
I did an initial rework of the scopes a few days ago.
I dismissed the idea of building on top of the current scopes very quickly because it is so ingrained in how Eloquent works at the moment.
The problem with my solution is that it isn't possible to use closures in attributes, that is a feature of the global scope. So we have to wait for php 8.5 to make that possible.
Yeah