@keizah7 I used a different method: I created a custom Builder class for the scopes.
For example, I have students who attend different classes on different dates. I made a StudentBulder class like this:
namespace App\Builders;
use Illuminate\Database\Eloquent\Builder;
class StudentBuilder extends Builder
{
protected function withCurrentClass(): self
{
return $this->withClass();
}
public function withClassAsOf($date, ?string $prefix = null): self
{
return $this->withClass($date, $prefix);
}
private function withClass($date = null, ?string $prefix = null): self
{
// extremely complex query here
return $this;
}
}
Then, on my Student class, I overrode the query() method:
public function newModelQuery() : StudentBuilder
{
$eloquentBuilder = new StudentBuilder($this->newBaseQueryBuilder());
return $eloquentBuilder->setModel($this);
}
Finally, I added a PhpDoc line for the IDE to know that query() is returning the custom builder class:
* @method static StudentBuilder query()
I've been pretty happy with this setup. For example, I made it load students' current class on every query, unless when explicitly told not to. I don't have to do Student::query()->withCurrentClass()->find(1) , just doing Student::find(1) is enough, so the data I get from my queries is much more consistent. And, yes, as long as you start with Student::query() the IDE's autocomplete works perfectly.