Open garak opened 6 years ago
Well, this doc is perfectly valid today. The only change with autowiring is that you can remove the definition of the constructor arguments (the FactoryInterface implementation can be injected by the autowiring).
I have a new feature in my TODO list which will make it much easier to use the library in alongside autoconfiguration. But it is not there yet
I know the docs are still valid, but I think it's a pity to miss showing the new features. I think docs should be expanded to cover both options, the old ones and the new ones. Other doubts: is there currently a way to avoid declaring a menu? For example, this is my current declaration:
app.menu.main:
class: Knp\Menu\MenuItem
factory: ['@App\Menu\Builder', createMenu]
tags:
- { name: knp_menu.menu, alias: main }
Can I exploit somehow the autowiring/autoconfigure?
+1
@garak only in my head. I know exactly how I want this to work for autoconfiguration, but I have not written the code yet (I need a few hours available for that but I'm quite busy these days)
Sorry for bumping (I know it's not really nice), but I was wondering if there are some news here.
This works, apparently:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\Menu\:
resource: '../../src/AppBundle/Menu/*'
AppBundle\Menu\Builder:
tags:
- { name: knp_menu.menu_builder, method: mainMenu, alias: main }
{{ knp_menu_render('main', { 'template': 'knpmenu/knp_menu.html.twig' }) }}
But I couldn't get it working without the tag. If I try to render the menu like this
{{ knp_menu_render('AppBundle:Builder:mainMenu', { 'template': 'knpmenu/knp_menu.html.twig' }) }}
BuilderAliasProvider
tries to instanciate it without any of its dependencies.
This is my idea for autowiring menu builders: we can create an interface and add tag/alias to all classes implementing it. Something like:
<?php
namespace Knp\Bundle\MenuBundle;
use Knp\Menu\ItemInterface;
interface MenuBuilderInterface
{
public function build(): ItemInterface;
public function getAlias(): string;
}
I added support of autoconfigurable menu builder services in my apps using an interface, I think people following this issue might be interested in the code :
// Here the usage
namespace App\Menu;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
class SidebarBuilder implements MenuBuilderInterface
{
private FactoryInterface $factory;
public function __construct(FactoryInterface $factory)
{
$this->factory = $factory;
}
static public function getAlias(): string
{
return 'sidebar';
}
public function build(array $options): ItemInterface
{
$menu = $this->factory->createItem('root');
$menu->addChild('Home', ['route' => 'hompage']);
return $menu;
}
}
The interface is inspired by the autoconfigurable Symfony 4.2 FormTypeExtensionInterface. I don't use multiple builders in a service but an interface like EventSubscriberInterface could be provided instead of the one I used to allow this usage.
This works with a compiler pass adding menu builder services to those managed by the bundle (tagged by knp_menu.menu_builder
and knp_menu.menu
) in the lazy provider used by the bundle.
I chose to use the existing provider because I couldn't find a good reason to register a dedicated provider. If you fear the friction with the bundle you can instead register a separated provider.
If the maintainers are ok with an autoconfigurable interface in the bundle I can make a merge request (not with this solution of course)
@wryk yes please!
I started the work a few years ago in #392, but I never finished it
Current docs are still showing the old approach (e.g. the one working with Symfony < 3.4). We need to cover also the new autowiring features of Symfony 3.4/4.0