Консольное приложение Symfony: внедрение зависимостей
Новичок Symfony здесь. После прочтения некоторой документации Symfony и некоторых ответов здесь, в SO, я теперь почти полностью запутался. Я пытаюсь использовать компонент консольного приложения и создать маленькое консольное приложение с поддержкой базы данных.
Многие утверждают, что для использования функций DI Symfony достаточно унаследовать мой командный класс не от Symfony\Component\Console\Command\Command, а от ContainerAwareCommand. Однако, когда я пытаюсь это сделать, я получаю ошибку Method Not Found при вызове application::getKernel().
У меня такое ощущение, что функции DI на самом деле недоступны в консольном приложении, основанном на компоненте консоли. Есть ли другой вид консольного приложения Symfony, например, основанный на полномасштабной среде?
Мне очень нравится простая структура, предоставляемая консольным компонентом Symfony\Component\Console\Application. Но тогда возникает вопрос - что делать для внедрения зависимостей и DBAL? Кажется, что все примеры, которые я нахожу, ссылаются на полную платформу Symfony и еще больше запутывают меня.
4 ответа
Просто быстрое обновление моего прогресса, если кто-нибудь наткнется на те же проблемы.
- Я включил в свой проект инфраструктуру внедрения зависимостей PHP-DI, которая, кажется, работает довольно хорошо без какой-либо конфигурации (пока) - на самом деле она довольно многое выясняет, если подумать.
- Точно так же Doctrine\DBAL включена в качестве отдельной библиотеки (я выбрал ее часть O/RM, так как это действительно крошечный проект, и я гораздо прочнее с SQL, чем с чем-либо еще) и с подключением просто возвращается провайдером соединения, который вводится везде, где это необходимо DI.
Одна вещь, которую я не мог понять, - это как создавать экземпляры командных классов библиотекой DI без моей помощи, поэтому мне фактически пришлось внедрить сам контейнер в мой переопределенный класс приложения и переопределить getDefaultCommands()
где я затем вытаскиваю экземпляры из контейнера вручную. Не идеально, но придется сделать сейчас.
Если ваша команда расширяется ContainerAwareCommand
...
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
...
class MyCommand extends ContainerAwareCommand
{
Контейнер DI доступен с getContainer()
метод. (как в стандартном контроллере), например:
$this->validator = $this->getContainer()->get('validator');
Я не знаю, актуален ли ваш вопрос, но у меня есть ответ, когда я наткнулся на ту же проблему здесь.
Вам просто нужно создать ядро самостоятельно и передать его в \Symfony\Bundle\FrameworkBundle\Console\Application, которая расширяет базовую \Symfony\Component\Console\Application.
<?php
// CronRun.php
require __DIR__.'/../../../../vendor/autoload.php';
require_once __DIR__.'/../../../../app/AppKernel.php';
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);
$application->add(new \KingdomHall\TaskBundle\Command\CronCommand());
$input = new \Symfony\Component\Console\Input\StringInput('k:c:r');
$application->run($input);
Вы можете использовать решение, которое я только что отправил на packagist.org. Включает в себя полностью рабочий symfony/independency-injection. Вы можете попробовать. используйте композитор для создания собственного проекта
composer create-project coral-media/crune project_dir
или просто клонируйте репозиторий. https://packagist.org/packages/coral-media/crune Вам нужно только установить зависимости DBAL (я не предлагаю ORM, если он вам действительно не нужен). Настройте параметры подключения в
.env
и просто определите службу для обработки соединения. Эта служба может быть внедрена в ваши команды с помощью общедоступных
setMyService($myService)
метод с
@required
аннотация. Также вы можете создать класс Connection и привязать его как параметр в вашем
command
конструктор.
crune
Шаблон также поддерживает функции автоподключения и автонастройки.