web-dev-qa-db-ja.com

symfony2グローバルヘルパー関数(サービス)でサービスコンテナーにアクセスする方法は?

この質問は、変数をsymfony2グローバルヘルパー関数(サービス)に渡せなかった理由を理解していないことから始まりましたが、私よりも明るい人々のおかげで、私のエラーは、注入しないで...

これが最終結果であり、動作するコードです。これを地域社会に役立たせる良い方法は見つかりませんでした。

これは、symfony2のグローバル関数またはヘルパー関数内からsecurity_contextからユーザーおよびその他のデータを取得する方法です。

次のクラスと関数があります。

<?php
namespace BizTV\CommonBundle\Helper;

use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class globalHelper {    

private $container;

public function __construct(Container $container) {
    $this->container = $container;
}   

    //This is a helper function that checks the permission on a single container
    public function hasAccess($container)
    {
        $user = $this->container->get('security.context')->getToken()->getUser();

        //do my stuff
    }     
}

...このように(app/config/config.ymlで)サービスとして定義...

#Registering my global helper functions            
services:
  biztv.helper.globalHelper:
    class: BizTV\CommonBundle\Helper\globalHelper
    arguments: ['@service_container']

さて、コントローラーでこの関数を次のように呼び出します...

public function createAction($id) {

    //do some stuff, transform $id into $entity of my type...

    //Check if that container is within the company, and if user has access to it.
    $helper = $this->get('biztv.helper.globalHelper');
    $access = $helper->hasAccess($entity);
54
Matt Welander

プロパティとコンストラクターを追加する前に最初のエラー(未定義のプロパティ)が発生したと仮定します。次に、2番目のエラーが発生しました。この他のエラーは、コンストラクターがContainerオブジェクトを受け取ることを期待しているが、何も受け取っていないことを意味します。これは、サービスを定義したときに、コンテナを取得することをDependency Injectionマネージャーに通知しなかったためです。サービス定義をこれに変更します。

services:
  biztv.helper.globalHelper:
    class: BizTV\CommonBundle\Helper\globalHelper
    arguments: ['@service_container']

コンストラクターは、Symfony\Component\DependencyInjection\ContainerInterface型のオブジェクトを予期する必要があります。

use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class globalHelper {    

    private $container;

    public function __construct(Container $container) {
        $this->container = $container;
    }
84
Carlos Granados

オブジェクト指向のベストプラクティスではないにもかかわらず、常に機能するアプローチ

global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');‏
24

別のオプションは、ContainerAwareを拡張することです。

use Symfony\Component\DependencyInjection\ContainerAware;

class MyService extends ContainerAware
{
    ....
}

サービス宣言でsetContainerを呼び出すことができます:

foo.my_service:
    class: Foo\Bundle\Bar\Service\MyService
    calls:
        - [setContainer, [@service_container]]

その後、次のようにサービス内のコンテナを参照できます。

$container = $this->container;
8
Jonathan

たぶんそれは最善の方法ではありませんが、私がやることは、コンテナをクラスに渡すことですので、必要になるたびにコンテナを持っています。

$helpers = new Helpers();
or
$helpers = new Helpers($this->container);

/* My Class */
class Helpers
{
    private $container;

    public function __construct($container = null) {
        $this->container = $container;
    }
    ...
}

私のために毎回動作します。

1
Strabek

サービスにservice_containerを挿入しないでください。例では、代わりに古いsecurity.contextまたはより新しいsecurity.token_storageを挿入する必要があります。たとえば、 http://symfony.com/doc/current/components/dependency_injection.html の「コンテナに依存するコードの回避」セクションを参照してください。

例:

<?php
namespace BizTV\CommonBundle\Helper;

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

class globalHelper {    

    private $securityTokenStorage;

    public function __construct(TokenStorage $securityTokenStorage) {
        $this->securityTokenStorage= $securityTokenStorage;
    }   


    public function hasAccess($container)
    {
        $user = $this->securityTokenStorage->getToken()->getUser();

        //do my stuff
    }     
}

app/config/config.yml:

services:
  biztv.helper.globalHelper:
    class: BizTV\CommonBundle\Helper\globalHelper
    arguments: ['@security.token_storage']

コントローラー:

public function createAction($id) {

    $helper = $this->get('biztv.helper.globalHelper');
    $access = $helper->hasAccess($entity);
1
Tsounabe