Я использую Laravel 8 и хочу получить все классы, реализующие интерфейс X.
Я сделал это с symfony4 несколько месяцев назад с DI:
services.yml
_instanceof:
App\Calculator\Budget\BudgetCalculatorInterface:
tags: ['app.budget_calculator']
App\Handler\CalculatorBudgetHandler:
arguments: [!tagged app.budget_calculator]
а затем в моем классе CalculatorBudgetHandler.php
private $calculatorList = [];
public function __construct(iterable $calculatorList)
{
$this->calculatorList = $calculatorList;
}
public function __construct(iterable $calculatorList)
{
$this->calculatorList = $calculatorList;
}
public function calculate(array $data): float
{
foreach ($this->calculatorList as $calculator) {
if ($calculator->supports($data)) {
return $calculator->calculate($data);
}
}
}
но я не понимаю, как это сделать с Laravel. Я думаю, мне нужно передать все мои классы в привязке или теге:
$this->app->tag([CpuReport::class, MemoryReport::class], 'reports');
это означает, что если у меня есть новый класс, реализующий X, я должен добавить его в привязку / тег? Я хочу делать это автоматически.
Спасибо !
@matiaslauriti уже прочитал это, но до сих пор не понимаю, как я получу все свои классы?
извините, что вы не понимаете? вы можете дополнить свой вопрос примером? Если вы скажете «все еще не могу понять, как я получу все мои классы», вы потеряли меня там, объясните подробнее.
@matiaslauriti Я обновил свой пример с помощью symfony. предположим, что у вас есть 3 класса: A, B, C, все реализующие интерфейс X. Я хочу получить все классы, реализующие X в итерируемом / массиве, для foreach в этих классах, в обработчике, команде или чем-то еще. и если я создаю новый класс D, реализующий X, я не хочу добавить новую строку, например $ this-> app-> bind (InterfaceX :: class, ClassD :: class); В основном в моем примере с symfony все мои классы, реализующие интерфейс, помечены, и с помощью DI я отправляю все эти помеченные классы в обработчик
Я все еще не понимаю, извините. Вы говорите, что не хотите делать $this->app->bind(InterfaceX::class, ClassA::class);, а затем ClassB, ClassC, и если у вас есть новый, например ClassD, тоже не делайте этого снова? Если вы ответили «да», вы не сможете сделать даже больше 1, если вы сделаете больше 1 bind, вы замените класс. Идея interface состоит в том, чтобы всегда возвращать один и тот же класс для этого интерфейса. Я думаю, вы можете указать, что в контроллере X вам нужен ClassA, но на контроллере Y вам нужен ClassB (с использованием интерфейсов), но это не нормально для Laravel.
Вы можете сделать public function __construct(ClassA $class) и на другом контроллере или классе public function __construct(ClassB $class), и он будет автоматически введен Laravel.
то, что вы делали на Symfony, не имеет смысла, зачем вам интерфейс, но нужно определить, что ему нужно (разные классы на каждом контроллере)? Имеет смысл, чтобы каждый класс реализовывал интерфейс, но когда вы переходите к каждому контроллеру, явно определяйте, что вам нужно, поскольку этот контроллер уникален для маршрута, он не является «многоцелевым» (поэтому не имеет смысла).
Как вы, возможно, сейчас, если вам требуется Model для каждого маршрута, вам не требуется его интерфейс (не имеет значения, существует он или нет), вам явно требуется модель, которая вам нужна. Сделайте то же самое со своим примером. Идея интерфейса binding состоит в том, чтобы требовать интерфейс везде, где вам нужен единственный связанный класс.
@matiaslauriti покажи это другим способом, без интерфейсов. я должен отправить товары. У меня есть класс для каждого оператора (ups, fedex ...), чтобы выбрать моего оператора. У меня есть свойство (или несколько свойств) для проверки в модели продукта. я хочу избежать в моем обработчике большого переключателя или, если так: if ($ productModl-> property == '' foo ") {$ carrier = new UpsCarrier ();} elseif () ... так что мне нравится находить способ зацикливаться на всех моих несущих классах, как в моем примере в symfony. для этого мне нужен способ внедрить все эти классы в мой конструктор или каким-либо другим способом их получить.
@matiaslauritii не понял ваш комментарий к моему коду Symfony? Я не использую это в контроллере.
Хорошо, позвольте мне спросить еще раз: где вы пытаетесь использовать этот код? Вижу класс CalculatorBudgetHandler. Где используется этот класс? Можете дать мне больше информации? Он используется в контроллере? Что вы передаете этому классу обработчика? Я думаю, что ваше исправление будет заключаться в том, чтобы понять шаблон, который вы используете, и, возможно, сделать это в стиле Laravel с шаблоном или изменить его на другой, который станет лучше вместе с Laravel.
О, теперь я думаю, что понимаю. Итак, вы хотите иметь массив классов для итерации, но эти классы реализуют один и тот же интерфейс, поэтому, если вам нужен InterfaceX, вы хотите получить все классы, реализующие этот интерфейс, верно?
@matiaslauriti да в основном. но интерфейс может быть не лучшим способом сделать это. Мне просто нужен способ получить все мои классы-носители, и если создать новый (PostCanadaCarrier.php или что-то еще), он должен быть автоматически в массиве классов. Если это возможно.
Вы можете добиться чего-то подобного, но более сложного, вы можете следить за этим и, когда вам требуется итерация, вернуть массив желаемых классов, но я не уверен на 100%, что это сработает. Никогда так не делал!






У вас должен связывать интерфейс, это действительно просто! Ознакомьтесь с документацией ...