В Symfony 4 я пытаюсь добавить элементы меню администратора с помощью CompilerPasses. Например, у меня есть класс Dashboard
который является MenuItem
Панель инструментов (menuItem)
#src/Menu/MenuItems/
/**
* Dashboard
*/
namespace App\Menu\MenuItems;
use App\Menu\MenuItem;
class Dashboard extends MenuItem
{
const KEY = 'dashboard.menu.item';
public function getKey(): string
{
return static::KEY;
}
/**
* Init menu item
*
* @return MenuItem
*/
public function init(): MenuItem
{
$this->setName('Dashboard');
$path = $this->router->generate('dashboard');
$this->setPath($path);
return $this;
}
}
В ядре я зарегистрировал свой CompilerPass под названием AdminMenuItemCompilerPass. Этот компилятор сканирует каталог MenuItems и добавляет MenuItems в качестве службы в контейнер.
AdminMenuItemCompilerPass
#scr/DependencyInjection/Compiler/
/**
* AdminMenuItemCompilerPass
*/
namespace App\DependencyInjection\Compiler;
use App\Menu\AdminMenu;
use App\Menu\MenuItem;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
/**
* Class AdminMenuItemCompilerPass
*/
class AdminMenuItemCompilerPass implements CompilerPassInterface
{
const BHAM_ADMIN_MENU_ITEMS = 'bham.admin.menu.item';
/**
* @var string
*/
private $srcDir;
public function __construct(string $srcDir)
{
$this->srcDir = $srcDir;
}
/**
* You can modify the container here before it is dumped to PHP code.
* @param ContainerBuilder $container
* @param string $namespace
*/
public function process(ContainerBuilder $container, $namespace = 'App'): void
{
$component = 'Menu/MenuItems';
$fs = new Filesystem();
if ($fs->exists($path = $this->srcDir . $component)) {
$finder = new Finder();
/** @var SplFileInfo $file */
foreach ($finder->files()->in($path)->depth('0') as $file) {
$class = str_replace('/', '\\', $namespace . '/' .$component . '/' . str_replace('.php', '', $file->getFilename()));
$definition = $container->hasDefinition($class) ? $container->getDefinition($class) : new Definition($class);
$definition->setPublic(true);
$definition->setAutowired(true);
$definition->addTag(static::BHAM_ADMIN_MENU_ITEMS);
// how to get menu item key here eq: Dashboard::KEY (dashboard.menu.item) ??
$definition->addTag('HOW_TO_GET_MENU_ITEM_KEY_HERE??');
$container->setDefinition($class, $definition);
}
}
}
}
В рамках процесса функции я перебираю все элементы MenuIms, но как получить КЛЮЧ и использовать его в качестве тега?
Я попробовал следующее в AdminMenuItemCompilerPass
public function process(ContainerBuilder $container, $namespace = 'App'): void
{
$component = 'Menu/MenuItems';
$fs = new Filesystem();
if ($fs->exists($path = $this->srcDir . $component)) {
$finder = new Finder();
/** @var SplFileInfo $file */
foreach ($finder->files()->in($path)->depth('0') as $file) {
$class = str_replace('/', '\\', $namespace . '/' .$component . '/' . str_replace('.php', '', $file->getFilename()));
$definition = $container->hasDefinition($class) ? $container->getDefinition($class) : new Definition($class);
$definition->setPublic(true);
$definition->setAutowired(true);
$definition->addTag(static::BHAM_ADMIN_MENU_ITEMS);
// not working
$action = 'getKey';
if (is_callable(array($definition->getClass(), $action))) {
$callMethod = call_user_func(array($definition->getClass(), $action)); // not working
$callMethod = call_user_func(array(new Reference($definition->getClass()), $action)); // not working
}
... rest goes here
Задача ещё не решена.
Других решений пока нет …