9457

Symfony dependency injection in twig extension

Ok, I was trying to create twig extension with dependencies on other service (security.context) and got some troubles. So, here is my service declaration:

acme.twig.user_extension: class: Acme\BaseBundle\Twig\UserExtension arguments: ["@security.context"] tags: - { name: twig.extension }

and here's my class

// acme/basebundle/twig/userextension.php namespace Acme\BaseBundle\Twig; use Symfony\Component\Security\Core\SecurityContext; use Acme\UserBundle\Entity\User; class UserExtension extends \Twig_Extension { protected $context; public function __construct(SecurityContext $context){ $this->context = $context; } public function getFunctions() { return array( 'getAbcData' => new \Twig_SimpleFunction('getAbcData', $this->getAbcData()), ); } public function getAbcData() { if ( !is_object($user = $this->context->getToken()->getUser()) || !$user instanceof User){ return null; } return array( 'data_array' => $user->getData(), ); } public function getName() { return 'user_extension'; } }

Finally, I have an error:

FatalErrorException: Error: Call to a member function getUser() on a non-object in \src\Acme\BaseBundle\Twig\UserExtension.php line 27

I guess that security.context service is not initialized yet, then i get an error. Could anyone tell, please, is there are ways to load service manually, or any better solutions for an issue? Thanks a lot.

<hr>

I use Symfony 2.5.*

UPD:

I've also found this notice in symfony docs

Keep in mind that Twig Extensions are not lazily loaded. This means that there's a higher chance that you'll get a CircularReferenceException or a ScopeWideningInjectionException if any services (or your Twig Extension in this case) are dependent on the request service. For more information take a look at How to Work with Scopes. Actually, I have no idea about how to do it correct..

Answer1:

You are <strong>calling</strong> $this->getAbcData() when constructing Twig_SimpleFilter. But you have to pass a callable as argument.

public function getFunctions() { return array ( 'getAbcData' => new \Twig_SimpleFunction( 'getAbcData', array( $this, 'getAbcData' )) ); }

Leo is also right. You should check first if getToken() is returning an object before trying getToken()->getUser().

You can also pass the user to the function as a parameter in twig: {{ getAbcData(app.user) }}. This way the function is more generic and could be used for any user, not just the currently logged in one.

Answer2:

This should probably work. The error message means that getToken() is not an object so you have to test if getToken() is an object before testing if getUser() is also is an object.

public function getAbcData() { $token = $this->context->getToken(); if (!is_object($token) || !is_object($token->getUser())) { return null; } return array( 'data_array' => $user->getData(), ); }

Answer3:

You need to change your twig extension to have the container not the security context passed into the constructor.

Twig_Extensions are special in that the normal rule of don't pass in the container but instead pass in only what you need often doesn't apply as it causes problems due to scope issues.

So change your extension to be like this.

// acme/basebundle/twig/userextension.php namespace Acme\BaseBundle\Twig; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\SecurityContext; use Acme\UserBundle\Entity\User; class UserExtension extends \Twig_Extension { /** * @var \Symfony\Component\DependencyInjection\ContainerInterface */ protected $container; public function __construct(ContainerInterface $container){ $this->container = $container; } public function getFunctions() { return array( 'getAbcData' => new \Twig_SimpleFunction('getAbcData', $this->getAbcData()), ); } public function getAbcData() { if ( !is_object($user = $this->container->get('security.context')->getToken()->getUser()) || !$user instanceof User){ return null; } return array( 'data_array' => $user->getData(), ); } public function getName() { return 'user_extension'; } }

Recommend

  • Random date in a view with Twig
  • php recursion global variable?
  • PHP and variable variables ($$) syntax
  • Using one class's properties in another OOP PHP
  • User locale does not work at first request
  • promise.all not access in rejection function
  • redirecting from admin page to a postAction on frontend
  • Spring Boot: How to use multiple schemas and dynamically choose which one to use for every request a
  • Using Symfony2 UserPassword validator in form type
  • Get data from database Android
  • How to translate specific content in website
  • how to I get the Facebook profile photo with PHP?
  • Display original Sitecore username instead of what's currently typed in
  • How to send message to news feed with facebook sdk php
  • Xml exception due to leading unicode character in REST API response
  • php: efficiently running functions with one-time loaded classes multiple times in optional files
  • Symfony dependency injection in twig extension
  • Node.js & Express routing with parameters
  • Using sfFilter to update DB with Doctrine
  • How do you run a function on the result of NgFor in Angular2?
  • How do I invalidate a bad authentication cookie early in the request?
  • SimpleMembershipProvider in MVC4 throws NotSupportedException on methods when initialized
  • Async setup of environment with Jest
  • second dropdown menu not selected
  • PHP: Overriding parent methods with __call
  • array from php to JavaScript
  • Best Way to create configuration file(config.php) php
  • Wait for subscription to complete
  • Angular2 How to display localStorage value inside HTML5 template?
  • How to prevent TreeItem selection?
  • Symfony2 - Doctrine - no changeset in post update
  • Linker errors when using intrinsic function via function pointer
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • Turn off referential integrity in Derby? is it possible?
  • LevelDB C iterator
  • Authorize attributes not working in MVC 4
  • Busy indicator not showing up in wpf window [duplicate]
  • How can i traverse a binary tree from right to left in java?
  • Python/Django TangoWithDjango Models and Databases
  • Net Present Value in Excel for Grouped Recurring CF