0

Gist で共有されているこのコードを見つけました (どこかでリンクを失った)。そのようなものが必要だったので、アプリケーションで使用し始めましたが、まだ完全には理解していないため、いくつかの問題が発生しています。

KnpMenuBundle と動的手段を使用して動的メニューを作成しようとしています。ある時点で、データベースを介してアクセス許可を確認する必要があり、コントローラーからルートを読み取ることができれば理想的ですが、これは別のタスクであり、おそらく注釈を作成することができますその時が来たら、別のトピックを開きます。

現在、SecurityContext にアクセスして、ユーザーがログに記録されているかどうかを確認する必要がありますが、その方法はわかりません。

私はメニューをレンダリングしていますがRequestVoter(私は思う)、これがコードです:

namespace PlantillaBundle\Menu;

use Knp\Menu\ItemInterface;
use Knp\Menu\Matcher\Voter\VoterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface; 

class RequestVoter implements VoterInterface {

    private $container;

    private $securityContext; 

    public function __construct(ContainerInterface $container, SecurityContextInterface $securityContext)
    {
        $this->container = $container;
        $this->securityContext = $securityContext;
    }

    public function matchItem(ItemInterface $item)
    {
        if ($item->getUri() === $this->container->get('request')->getRequestUri())
        {
            // URL's completely match
            return true;
        }
        else if ($item->getUri() !== $this->container->get('request')->getBaseUrl() . '/' && (substr($this->container->get('request')->getRequestUri(), 0, strlen($item->getUri())) === $item->getUri()))
        {
            // URL isn't just "/" and the first part of the URL match
            return true;
        }
        return null;
    }

}

に関連するすべてのコードsecurityContextは、menuBuilder. これは、メニューを作成しているコードです。

namespace PlantillaBundle\Menu;

use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAware;

class MenuBuilder extends ContainerAware {

    public function mainMenu(FactoryInterface $factory, array $options)
    {
        // and here is where I need to access securityContext 
        // and in the near future EntityManger

        $user = $this->securityContext->getToken()->getUser();
        $logged_in = $this->securityContext->isGranted('IS_AUTHENTICATED_FULLY');

        $menu = $factory->createItem('root');
        $menu->setChildrenAttribute('class', 'nav');

        if ($logged_in)
        {
            $menu->addChild('Home', array('route' => 'home'))->setAttribute('icon', 'fa fa-list');
        }
        else
        {
            $menu->addChild('Some Menu');
        }

        return $menu;
    }     

}

しかし、メソッドに渡していないため、これは完全に間違っていsecurityContextます。方法がわからず、このエラーが発生しています。

テンプレートのレンダリング中に例外がスローされました (「通知: 未定義のプロパティ: PlantillaBundle\Menu\MenuBuilder::$securityContext in /var/www/html/src/PlantillaBundle/Menu/MenuBuilder.php 12 行目」) / var/www/html/src/PlantillaBundle/Resources/views/menu.html.twig の 2 行目。

投票者は次のように定義さservices.ymlれます。

plantilla.menu.voter.request:
    class: PlantillaBundle\Menu\RequestVoter
    arguments:
        - @service_container
        - @security.context
    tags:
        - { name: knp_menu.voter }

では、どのように注入securityContextし (同じ手順になると思われるので、EntityManager は要求しません)、menuBuilder からアクセスしますか?

更新: コードのリファクタリング

したがって、@Cerad の提案に従って、この変更を行いました。

services.yml

services:
    plantilla.menu_builder:
        class: PlantillaBundle\Menu\MenuBuilder
        arguments: ["@knp_menu.factory", "@security.context"]

    plantilla.frontend_menu_builder:
        class: Knp\Menu\MenuItem # the service definition requires setting the class
        factory_service: plantilla.menu_builder
        factory_method: createMainMenu
        arguments: ["@request_stack"]
        tags:
            - { name: knp_menu.menu, alias: frontend_menu } 

MenuBuilder.php

namespace PlantillaBundle\Menu;

use Knp\Menu\FactoryInterface;
use Symfony\Component\HttpFoundation\RequestStack;

class MenuBuilder {

    /**
     * @var Symfony\Component\Form\FormFactory $factory
     */
    private $factory;

    /**
     * @var Symfony\Component\Security\Core\SecurityContext $securityContext
     */
    private $securityContext;

    /**
     * @param FactoryInterface $factory
     */
    public function __construct(FactoryInterface $factory, $securityContext)
    {
        $this->factory = $factory;
        $this->securityContext = $securityContext;
    }

    public function createMainMenu(RequestStack $request)
    {
        $user = $this->securityContext->getToken()->getUser();
        $logged_in = $this->securityContext->isGranted('IS_AUTHENTICATED_FULLY');

        $menu = $this->factory->createItem('root');
        $menu->setChildrenAttribute('class', 'nav');

        if ($logged_in)
        {
            $menu->addChild('Home', array('route' => 'home'))->setAttribute('icon', 'fa fa-list');
        }
        else
        {
            $menu->addChild('Some Menu');
        }

        return $menu;
    }

}

Abd ib 私のテンプレートはメニューをレンダリングするだけです{{ knp_menu_render('frontend_menu') }}が、FontAwesome 部分が失われ、機能する前に、なぜですか?

4

2 に答える 2

1

コメント リクエストによると、メニュー ビルダーは次のようになります。

namespace PlantillaBundle\Menu;

use Knp\Menu\FactoryInterface;

class MenuBuilder {

    protected $securityContext;

    public function __construct($securityContext)
    {
        $this->securityContext = $securityContext;
    }
    public function mainMenu(FactoryInterface $factory, array $options)
    {
        // and here is where I need to access securityContext 
        // and in the near future EntityManger

        $user = $this->securityContext->getToken()->getUser();
        ...

// services.yml
plantilla.menu.builder:
    class: PlantillaBundle\Menu\MenuBuilder
    arguments:
        - '@security.context'

// controller
$menuBuilder = $this->container->get('plantilla.menu.builder');

セキュリティ コンテキスト サービスのみが必要なため、ビルダー コンテナーを認識させる必要がないことに注意してください。もちろん、エンティティ マネージャーを注入することもできます。

================================

投票者に関しては、現在、ユーザーがログインしているかどうかを確認するだけです。したがって、投票者は実際には必要ありません。しかし、特定のユーザー (管理者など) が追加のメニュー項目にアクセスできるとします。すべてのセキュリティ チェック ロジックを投票者に移動できます。メニュー ビルダーのコードは次のようになります。

if ($this->securityContext->isGranted('view','homeMenuItem')
{
    $menu->addChild('Home', array('route' ...

つまり、誰がどのメニュー項目を取得するかをより細かく制御できます。

ただし、最初に MenuBuilder を機能させてから、必要に応じて有権者を追加してください。

于 2014-10-02T14:21:34.983 に答える