Подписывайтесь на наш Telegram канал и будьте в курсе всех событий.

Создание класса - бесплатное, но так как модели в Laravel уже "толстые" и в них уже замешана логика базы, то я не вижу смысла выносить запросы во внешний класс. Тем более что в этом случае "утекают" знания про структуру базы.

Лично для себя обнаружил что очень удобно использовать tap метод. Например,

final class AgentChallengeProgress extends Model
{
    public static function queryProgressChallenge(string $agencyId): callable
    {
        return static fn(Builder $builder): Builder => $builder
            ->where('status', '!=', self::STATUS_INACTIVE)
            ->where('agency_id', $agencyId);
    }
}

А в контроллере вызываем модель и его квери

/** @var AgentChallengeProgress|null $currentChallenge */
$currentChallenge = AgentChallengeProgress::query()
    ->tap(AgentChallengeProgress::queryProgressChallenge($agencyId))
    ->first();

Для меня плюс в том что запрос лежит сразу в модели, всё что я хочу скрыть - могу смело делать приватным.

Моё сугубо личное имхо - ваше решение порождает больше вопросов чем решает проблемы. Например,

$book->publish();

Такое будет подсвечено как предупреждение, так как данного метода нет в классе. То есть нужно провалиться в класс, найти newEloquentBuilder, зайти в него и найти в нём publish.