Этот вопрос начался со мной, не понимая, почему я не мог передавать переменные в глобальную вспомогательную функцию symfony2 (service), но благодаря людям, более ярким, чем я, я понял, что моя ошибка заключалась в попытке использовать security_context изнутри класс, который его не вводил так...
Это конечный результат, код, который работает. Я не нашел лучшего способа сделать это полезным для общения.
Вот как вы можете получить пользовательские и другие данные из security_context из глобальной функции или вспомогательной функции в symfony2.
У меня есть следующий класс и функция:
<?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);
Я предполагаю, что первая ошибка (свойство undefined) произошла до того, как вы добавили свойство и конструктор. Затем вы получили вторую ошибку. Эта другая ошибка означает, что ваш конструктор ожидает получить объект Container, но ничего не получил. Это связано с тем, что, когда вы определили свой сервис, вы не сказали менеджеру по взысканию зависимостей, что вы хотите получить контейнер. Измените определение сервиса следующим образом:
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;
}
Подход, который всегда работает, несмотря на то, что он не является лучшей практикой в OO
global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');
$kernel = null
... Но спасибо за это.
Другой вариант - расширить 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;
ContainerAware
который могут расширять другие классы. Скорее классы могут реализовать ContainerAwareInterface
в сочетании с использованием черты ContainerAwareTrait
Вы не должны вводить 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
}
}
приложение/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);
Может быть, это не лучший способ, но то, что я делаю, это передать контейнер классу, поэтому я получаю его каждый раз, когда мне это нужно.
$helpers = new Helpers();
or
$helpers = new Helpers($this->container);
/* My Class */
class Helpers
{
private $container;
public function __construct($container = null) {
$this->container = $container;
}
...
}
Работает каждый раз для меня.