A repository is a collection-like interface over persisted objects, and returning a query builder makes every caller a co-author of the persistence layer.
// not a repository: the caller composes SQL by proxy
public function query(): Builder
{
return Order::query();
}
// a repository: named questions, concrete answers
public function unpaidOlderThan(DateTimeImmutable $t): OrderCollection;
public function findBySku(Sku $sku): ?Order;
public function save(Order $order): void;
The builder version cannot be swapped for another implementation, cannot be faked in a test without a database, and spreads query knowledge across every caller — which is the whole set of things a repository exists to prevent. The honest position is that if you want the builder’s flexibility then use the ORM directly and skip the indirection, because a repository that leaks the builder is a folder with a suggestive name. The method count growing is a real cost and a real signal.