Вообще можно делать SQL-запрос не сразу, а после какого-то toResult():
PHP:
$userRepository->findSatisfying($spec)->limit(42)->orderBy("name")->toResult()
Чем-то похоже на SQL builder, но всё-таки не тот уровень.
Но признаюсь честно, на практике так и не пробовал. Expression trees, generics — всего этого не хватает. Все эти компромиссы напрягают.
я к примерно подобному пришел,
PHP:
$filterCollection->add(new MessageOrderByNameFiler)->add(new LimitMessageBy(42));
$userRepository->findSatisfying($spec)->filter($filterColelction)->toResult()
Ибо в OrderBy может быть бизнес логика, например, orderBy('active') и в контексте active сущность, это такая сущность, которая не expired, не обработана и со статусом waiting.
Во всем этом подходе смущает, что в базовой in memory коллекции фильтров имеет значение порядок добавления фильтров (если сначала сделать array_filter, а потом array_sort, то результат будет совершенно иным нежели сначала array_sort, а потом array_filter), а вот в наследуемом DQLFilter на это уже пофиг ибо все соберется в DQL строку
то есть нарушение явно какой-то есть, близкое к LSP, но другое...
Опять же как вариант, сделать коллекцию фильтров умнее - с приоритетами