Great questions! Let's clarify what's happening:
Why can’t you call findByName() or similar methods on QueryBuilder?
- Spatie's QueryBuilder is a query builder wrapper and does not inherit custom Eloquent methods (like
findByNamefrom Spatie's Permission package). findByNameis a static method on the Role model, not a query scope or Eloquent builder macro. The static method executes an internal query and returns a Role instance.- Query scopes (e.g.,
scopeActive) can be chained onto query builders, but static helper methods (likefindByName) cannot.
What to do instead?
1. Fetch a Role by Name and its Permissions
The Standard Eloquent way is the right way:
$role = Role::findByName('user', 'sanctum');
$permissions = $role->permissions;
Or eager load:
$role = Role::with('permissions')->findByName('user', 'sanctum');
2. Using QueryBuilder for Filtering (if you need query params/filters)
If you want to use Spatie QueryBuilder (maybe to support filters), filter by name instead, then eager load permissions:
$role = QueryBuilder::for(Role::class)
->allowedIncludes('permissions')
->where('name', 'user')
->first();
Or, if you want to use filters:
$role = QueryBuilder::for(Role::class)
->allowedFilters('name')
->allowedIncludes('permissions')
->where('name', 'user')
->first();
Or, with a query parameter:
/api/roles?filter[name]=user&include=permissions
Your code:
$role = QueryBuilder::for(Role::class)
->allowedFilters('name')
->allowedIncludes('permissions')
->first();
3. Summary Table
| Task | Solution |
|---|---|
| Role by name, permissions | Role::findByName(...)->permissions |
| QueryBuilder filters, includes | Use allowedFilters, allowedIncludes, and where('name', ...) |
Conclusion
- You cannot use
findByNameon the QueryBuilder. It's a static model method. - Use QueryBuilder’s filtering and relationships to filter by
nameand includepermissions, or stick with the Eloquent solution directly.
Example:
$role = QueryBuilder::for(Role::class)
->allowedFilters('name')
->allowedIncludes('permissions')
->where('name', 'user')
->first();
$permissions = $role ? $role->permissions : collect();
Let me know if you want to see a controller or route example!