Чуть позже обдумав - понял, что правило простое "если А зависит от Б, а Б зависит от А, нужно сделать В, от которого зависит и А и Б".
То есть ситуация - валидатору нужен путь, чтобы проверять путь, а пути нужен валидатор, чтобы проверять что-то ещё. В этом случае валидатор умеет всё проверять, а это самое "что-то ещё" делает третий обьект. в котором на входе и валидатор и путь.
Что по сути и написал
index0h, только в голове не хватало мозайки, что валидатор, проверив путь, должен вернуть "проверенный path", который не нужно проверять в другом классе еще раз.
устарело
По проблеме с циклическими зависимостями найдено решение. Кому интересно напишите, расскажу весь путь как шли и почему так. Спасибо Андрей Ковалёв, Алексей Пастушенко, еще один Алексей, Александру Захаренко, Human с t.me@oop_ru канала, Александру Markwhide и Ярославу Кравцову, и еще двум парням в телеге
1. Циклическая зависимость возникает когда нарушается принцип ООП - в зависимостях должны быть классы, которые меняются достаточно редко - а именно, когда происходит косяк или меняется задача. Не дополняется задача, а именно меняется то что было.
2. Частным случаем такой ситуации является желание разместить все методы класса в одном файле по причине того, что они чем-то похожи. Это говорит о том, что класс будет часто меняться - когда человеку понадобится новый функционал похожий на старый, он должен открыть этот файл, дописать в него, и закрыть. Это говорит о том что файл меняется часто и не может быть зависимостью!
3. В конкретном примере валидатор является сборкой методов, а должен быть их "загрузчиком" - создателем обьектов. Таким образом создавая новые классы мы расширяем валидатор не меняя сам валидатор. Тогда валидатор может быть передан в конструктор, его поведение не меняется.
4. Передача загрузчика в конструктор в случае написания тестов создаст проблему, что придется заменять заглушкой и валидатор и то, что он должен создать по запросу, покрывать это тестами. Поэтому в нужном месте в конструктор подсовывается не валидатор, а само правило валидации или класс процесса валидации, который может быть кем-то создан.
5. В этом случае будет наблюдаться ситуация когда казалось бы независимые модули просят зависимости друг у друга, хотя друг о друге не знают. Первый шаг это воткнуть интерфейс на определенное действие в конструктор, а по интерфейсу подсовывать исполнителя.
6. В пхп 7.3 ещё нельзя написать такой класс, который одновременно соответствует двум интерфейсам в двух разных модулях (как в фирме контракт нанимателя и контракт сотрудника) - таким образом приходится исходить из того что в рамках модуля зависимости можно переплетать. Есть способ - сделать обертку для класса и сунуть его зависимостью, а уже обертку повесить на собственный интерфейс, но тогда модулю нужен контейнер и конфиг который подсунет модуль в обертку параметром, и выдаст декорированный обьект. Если модулей несколько должно быть ядро, и код можно положить там. То есть модуль будет работать только с ядром. Либо делать компонент валидатора в каждом из модулей и копировать необходимые проверки, тогда модули можно безопасно выдергивать и вставлять. Да. Копирование кода.