ПРИМЕЧАНИЕ: я использую Symfony 4.3.1.Я опубликую это так, затем помогу вам переместить весь код из этой архитектуры в Symfony 3.4.
Я использую похожую концепцию для загрузки различных классов в моем проекте.Позвольте мне сначала объяснить, затем я добавлю код под этим текстом.
Во-первых, я загружаю пользовательский проход компилятора в src/Kernel.php
(ваш файл app/AppKernel.php
):
/**
* {@inheritDoc}
*/
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new BannerManagerPass());
}
BannerManagerPass
он создан в src/DependencyInjection/Compiler
(в вашем случае это должен быть src / BUNDLE / DependencyInjection / Compiler`).
class BannerManagerPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
if (!$container->has(BannerManager::class)) {
return;
}
$definition = $container->findDefinition(BannerManager::class);
$taggedServices = $container->findTaggedServiceIds('banner.process_banners');
foreach (array_keys($taggedServices) as $id) {
$definition->addMethodCall('addBannerType', [new Reference($id)]);
}
}
}
Как видите, этот класс должен реализовывать CompilerPassInterface
.Вы можете заметить, что я ищу определенные сервисы, помеченные как banner.process_banners .Я покажу, как я пометил службы чуть позже.Затем я вызываю addBannerType
метод из BannerManager
.
App \ Service \ BannerManager.php: (в вашем случае src / BUNDLE / Service / BannerManager.php)
class BannerManager
{
/**
* @var array
*/
private $bannerTypes = [];
/**
* @param BannerInterface $banner
*/
public function addBannerType(BannerInterface $banner)
{
$this->bannerTypes[$banner->getType()] = $banner;
}
/**
* @param string $type
*
* @return BannerInterface|null
*/
public function getBannerType(string $type)
{
if (!array_key_exists($type, $this->bannerTypes)) {
return null;
}
return $this->bannerTypes[$type];
}
/**
* Process request and return banner.
*
* @param string $type
* @param Server $server
* @param Request $request
*
* @return Response
*/
public function process(string $type, Server $server, Request $request)
{
return $this->getBannerType($type)->process($request, $server);
}
}
В этом классе есть собственный метод (созданный мной) с именем process()
.Вы можете назвать это как хотите, но я думаю, что это довольно многословно.Все параметры присланы мной, так что не против.Вы можете отправлять все, что захотите.
Теперь у нас есть менеджер и установлен проход компилятора.Пришло время установить типы наших баннеров (на основе моего примера) и пометить их!
Мои типы баннеров находятся в src / Service / Banner / Types (в вашем случае должно быть src / BUNDLE / Service / Wh независимоYouWant / Тип . Это не имеет значения! Вы можете изменить его позже из services.yaml).
Эти типы реализуют мой BannerInterface
.В данном случае не имеет значения код под классом.Еще одна вещь, которую я должен предупредить вас!Вы должны увидеть это под BannerManager, внутри addBannerType()
я звоню $banner->getType()
.Это один метод, унаследованный от BannerInterface в моем случае, и он имеет уникальную строку (в моем примере у меня есть три типа баннеров: маленький, нормальный, большой).Этот метод может иметь любое имя, но не забудьте также обновить его в своем менеджере.
Мы почти готовы!Мы должны пометить их, тогда мы готовы их попробовать!
Перейдите на your services.yaml и добавьте следующие строки:
App\Service\Banner\Types\:
resource: '../src/Service/Banner/Types/'
tags: [banner.process_banners]
Пожалуйста, посмотрите тег!
Чтобы я не показывал собственный баннер, я использую простой URL-адрес с $ _GET, где я сохраняю тип баннера, а затем загружаю его так:
public function view(?Server $server, Request $request, BannerManager $bannerManager)
{
...
return $bannerManager->getBannerType($request->query->get('slug'))->process($request, $server);
}