set session value in symfony2 view - symfony

I want to set session value in Symfony2 view both in PHP and TWIG . I can get the session value in view like this
$app->getSession()->get('whatever');
But didn't know how to set the session value in view . Kindly any one help .

This is your twig extension you can put this code under YourBundle/Twig/SessionExtension.php
namespace YourBundle\Twig;
use Symfony\Component\HttpFoundation\Session\Session;
class SessionExtension extends \Twig_Extension
{
private $session;
public function __construct(Session $session) {
$this->session = $session;
}
public function getFilters()
{
return array(
new \Twig_SimpleFilter('setSession', array($this, 'setSession')),
);
}
public function setSession($key, $val){
$this->session->set($key, $val);
return true;
}
public function getName()
{
return 'session_extension';
}
}
Add to service for twig;
yourbundle.twig.session_extension:
class: YourBundle\Twig\SessionExtension
arguments:
session: "#session"
tags:
- { name: twig.extension }
Now , you can use in twig;
{{ 'test'|setSession('myKey', 'myValue') }}

Related

2 Deprecations in my Symfony 3 Project

I have 2 deprecations in my Symfony 3 project when try to define a custom service in service.yml that I would like to solve but I don't get the way...
This my code FollowingExtension.php
<?php
namespace AppBundle\Twig;
use Symfony\Bridge\Doctrine\RegistryInterface;
class FollowingExtension extends \Twig_Extension {
protected $doctrine;
public function __construct(RegistryInterface $doctrine) {
$this->doctrine = $doctrine;
}
public function getFilters() {
return array(
new \Twig_SimpleFilter('following', array($this, 'followingFilter'))
);
}
public function followingFilter($user, $followed){
$following_repo = $this->doctrine->getRepository('BackendBundle:Following');
$user_following = $following_repo->findOneBy(array(
"user" => $user,
"followed" => $followed
));
if(!empty($user_following) && is_object($user_following)){
$result = true;
}else{
$result = false;
}
return $result;
}
public function getName() {
return 'following_extension';
}
}
And this is my services.yml:
following.twig_extension:
class: AppBundle\Twig\FollowingExtension
public: false
arguments:
$doctrine: "#doctrine"
tags:
- { name: twig.extension }
I would appreciate the help they gave me in trying to solve my problem.
First problem solution
It looks like because of registering services with duplicate name, as declared in your class:
`return 'following_extension';`
Make sure that you only have one twig service named following_extension. If you are sure that only one twig service named following_extension, you probably register more than one service using that class.
Second problem solution
Replace
`use Symfony\Bridge\Doctrine\RegistryInterface;`
with
`use Doctrine\Common\Persistence\ManagerInterface;`
and also replace
`public function __construct(RegistryInterface $doctrine) {`
with
`public function __construct(ManagerInterface $doctrine) {`
Finally solved the problem and i want share the info...
Reading the documentation of Symfony found this How to Create Service Aliases and Mark Services as Private and them I declared my service this way:
in service.yml:
following.twig_extension: '#AppBundle\Twig\FollowingExtension'
and FollowingExtension.php
<?php
namespace AppBundle\Twig;
use Doctrine\Common\Persistence\ManagerRegistry;
class FollowingExtension extends \Twig_Extension {
private $managerRegistry;
public function __construct(ManagerRegistry $managerRegistry) {
$this->managerRegistry = $managerRegistry;
}
public function getFilters() {
return array(
new \Twig_SimpleFilter('following', array($this, 'followingFilter'))
);
}
public function followingFilter($user, $followed){
$following_repo = $this->managerRegistry->getRepository('BackendBundle:Following');
$user_following = $following_repo->findOneBy(array(
"user" => $user,
"followed" => $followed
));
if(!empty($user_following) && is_object($user_following)){
$result = true;
}else{
$result = false;
}
return $result;
}
}
Thanks for helping me and I'm sorry if my english is bad.

Symfony2 - Twig extension does not exist in Twig file

I am trying to register (read the docs) a Twig extension and everything seems to be correct except it's not being found in the Twig file.
Getting the following error:
The function "getPostCount" does not exist in AcmeDemoBundle:Page:index.html.twig at line 17
Can someone show me what I am doing wrong?
services.yml
acme.twig.acme_extension:
class: Acme\DemoBundle\Twig\PostExtension
tags:
- { name: twig. extension }
arguments:
em: "#doctrine.orm.entity_manager"
PostExtension.php
class PostExtension extends \Twig_Extension
{
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function getFilters()
{
return array(
);
}
public function getFunctions()
{
return array(
'getPostCount' => new \Twig_Function_Method($this,'getPostCount')
);
}
public function getPostCount($year, $month)
{
return $this->$em->getRepository('AcmeDemoBundle:Post')
->getPostCountsByMonth($year, $month);
}
public function getName()
{
return 'post_extension';
}
}
Twig
{{ getPostCount('2014', 'July') }}
In services.yml:
Remove the extra space in twig.extension.
tags:
- { name: twig.extension }

Register Twig extensions and cache directory

I have problems with adding Twig extensions.
I have Bundle controllers extending custom BaseController class:
class DefaultController extends BaseController
And there's my BaseController class (only part of it).
class BaseController extends Controller {
public function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface $container = null)
{
parent::setContainer($container);
$this->onContainerSet();
}
public function onContainerSet()
{
// many other tasks
$this->get('twig')->addExtension(new \Twig_Extension_StringLoader());
$this->get('twig.loader')->addPath('../app');
$function = new \Twig_SimpleFunction('stars', function ($number, $maximum_stars = 5) {
$this->get('twig')->addGlobal('star_number',sprintf("%.1f",$number));
$this->get('twig')->addGlobal('star_max',$maximum_stars);
$full_stars = floor($number);
$half_stars = ($number - $full_stars) * 2;
$empty_stars = $maximum_stars - $full_stars - $half_stars;
$this->get('twig')->addGlobal('full_stars_number',$full_stars);
$this->get('twig')->addGlobal('half_stars_number',$half_stars);
$this->get('twig')->addGlobal('empty_stars_number',$empty_stars);
echo $this->renderView(
'views/stars.html.twig'
);;
});
$function2 = new \Twig_SimpleFunction('inurl', function ($anchor, $code) {
echo ''.$anchor."";
});
$this->get('twig')->addFunction($function);
$this->get('twig')->addFunction($function2);
}
}
The problem:
When I clear cache directory I have first message:
CRITICAL - Uncaught PHP Exception LogicException: "Unable to register
extension "string_loader" as extensions have already been
initialized." at ...\vendor\twig\twig\lib\Twig\Environment.php line
660 Context: {"exception":"Object(LogicException)"}
But when I reload page (cache folder is already created) it works fine (no exception).
However if I comment line:
// $this->get('twig')->addExtension(new \Twig_Extension_StringLoader());
and clear cache directory I have exception:
CRITICAL - Uncaught PHP Exception LogicException: "Unable to add
function "stars" as extensions have already been initialized." at
...\vendor\twig\twig\lib\Twig\Environment.php line 946 Context:
{"exception":"Object(LogicException)"}
So it seems that when cache directory doesn't exist from some reason adding any Twig extensions doesn't work (extensions have already been initialized) as I would like but when cache directory is already created everything works fine.
Question - how to solve it in the simplest way?
Create your class in YourBundle\Twig
class YourExtension extends \Twig_Extension
{
/**
* #var Router
*/
protected $router;
function __construct(Router $router)
{
$this->router = $router;
}
/**
* #return array
*/
public function getFilters()
{
return [
new \Twig_SimpleFilter('my_filter', [$this, 'myFilter'], ['is_safe' => ['html']]),
];
}
/**
* #return string
*/
public function myFilter(User $user)
{
return 'FILTERED: ' . $user->getName();
}
/**
* #return string
*/
public function getName()
{
return 'my_filter_extension';
}
}
Then, register your extension as a service: ( in this case I inject router as an argument )
yourbundle.twig.my_filter_extension:
class: Acme\YourBundle\Twig\YourExtension
arguments: [#router]
tags:
- { name: twig.extension }
If you want to enable Twig_Extension_StringLoader, add to your services:
yourbundle.twig.extension.loader:
class: Twig_Extension_StringLoader
tags:
- { name: 'twig.extension' }
Twig_Extension_StringLoader is not loaded by default.
What I finally did to achieve result (maybe someone will have similar problem in the future):
In config.yml I've added:
services:
yourbundle.twig.extension.loader:
class: Twig_Extension_StringLoader
tags:
- { name: 'twig.extension' }
yourbundle.twig.stars_extension:
class: Mnab\Twig\Stars
tags:
- { name: 'twig.extension' }
yourbundle.twig.inurl_extension:
class: Mnab\Twig\InternalUrl
tags:
- { name: 'twig.extension' }
in my BaseController I only left from question code:
$this->get('twig.loader')->addPath('../app');
but also added:
$this->get('twig')->addGlobal('internal_links',$this->internalLinks);
to use it in Twig extension
And I've create 2 classes:
<?php
//InternalUrl.php
namespace Mnab\Twig;
use Symfony\Component\DependencyInjection\ContainerInterface;
class InternalUrl extends \Twig_Extension {
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('inurl', array($this, 'inUrlFunction'), array('needs_environment' => true, 'is_safe' => array('html'))),
);
}
public function inUrlFunction(\Twig_Environment $env, $anchor, $code)
{
return ''.$anchor."";
}
public function getName()
{
return 'inurl_extension';
}
}
and
<?php
// Stars.php
namespace Mnab\Twig;
class Stars extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('stars', array($this, 'starsFunction'), array('needs_environment' => true, 'is_safe' => array('html'))),
);
}
public function starsFunction(\Twig_Environment $env, $number, $maximum_stars = 5)
{
$env->addGlobal('star_number',sprintf("%.1f",$number));
$env->addGlobal('star_max',$maximum_stars);
$full_stars = floor($number);
$half_stars = ($number - $full_stars) * 2;
$empty_stars = $maximum_stars - $full_stars - $half_stars;
$env->addGlobal('full_stars_number',$full_stars);
$env->addGlobal('half_stars_number',$half_stars);
$env->addGlobal('empty_stars_number',$empty_stars);
return $env->render(
'views/stars.html.twig'
);
}
public function getName()
{
return 'stars_extension';
}
}
Now it seems to work regardless of cache is created or not. So it seems to better register services when you want to use Twig Extensions than registering Extensions in Controller.

Trying to get this Twig (Symfony2) function extension to register

I'm getting an error:
"twig extension FatalErrorException: Error: Class Acme\Bundle\MyBundle\Twig not found in app/cache/dev/appDevDebugProjectContainer.php"
I've cleared the cache but this does nothing.
I'm just trying to test setting it up and then I can put in all my logic.
--
A file named MyTwigExtensions.php
namespace Acme\Bundle\MyBundle\Twig;
class MyTwigExtensions extends \Twig_Extension
{
public function getFunctions() {
return array(
new Twig_SimpleFunction('link', 'generate_link')
);
}
public function generate_link($params) {
return "THE-LINK-HERE";
}
public function getName() {
return "link";
}
}
In services.yml
services:
my_extension.twig.extension:
class: Acme\Bundle\MyBundle\Twig
arguments: []
tags:
- { name: twig.extension }
You have to enter fully qualified name of the extension class.
services:
my_extension.twig.extension:
class: Acme\Bundle\MyBundle\Twig\MyTwigExtensions # <--- here
arguments: []
tags:
- { name: twig.extension }
for service reprensetation format is sth like this. addArrowInCode below is the name of the method used in twig:
twig.extension.addArrowInCode:
class: Acme\DemoBundle\Twig\AddArrowInCodeExtension
tags:
- { name: twig.extension }
and for this extension you should have like...
class AddArrowInCodeExtension extends \Twig_Extension
{
function addArrowInCodeFilter($code, $separator = '⇒')
{
// do sth setting final
return $final;
}
/**
* Returns a list of filters to add to the existing list.
*
* #return array An array of filters
*/
public function getFilters()
{
return array(
'addArrowInCode' => new Twig_Filter_Method($this, 'addArrowInCodeFilter', array('needs_environment' => false)),
);
}
public function getName()
{
return 'addArrowInCode';
}
}
hope it helps
Please check this code.
namespace Acme\Bundle\MyBundle\Twig;
class MyTwigExtensions extends \Twig_Extension
{
public function getFunctions() {
return array(
new Twig_SimpleFunction('link', array($this, 'generate_link')) // <== changed here
);
}
public function generate_link($params) {
return "THE-LINK-HERE";
}
public function getName() {
return "link";
}
}
In services.yml
services:
my_extension.twig.extension:
class: Acme\Bundle\MyBundle\Twig\MyTwigExtensions # <== changed here
arguments: []
tags:
- { name: twig.extension }

Pass path parameters automatically

I'm building a site where the user can choose a country, state and city he wants.
Once he selects these parameters he goes to a page like this: en.example.com/spain/madrid/madrid/
The problem is, every time I want to build a new url, I must pass these 3 variables and I was wondering if I could do something to make them just like the _locale variable which symfony itself passes it to the parameters.
Thanks
After searching more I found this post: http://blog.viison.com/post/15619033835/symfony2-twig-extension-switch-locale-current-route
I just used the idea and made the changes I needed and this is the final code for my extension
<?php
namespace Comehoy\CoreBundle\Twig\Extension;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;
class PathExtension extends \Twig_Extension
{
private $request;
private $router;
public function __construct(Router $router) {
$this->router = $router;
}
public function onKernelRequest(GetResponseEvent $event) {
if ($event->getRequestType() === HttpKernel::MASTER_REQUEST) {
$this->request = $event->getRequest();
}
}
public function getFunctions()
{
return array(
'l10n_path' => new \Twig_Function_Method($this, 'getPath')
);
}
public function getPath($name, $parameters = array())
{
$parameters = array_merge($parameters, [
'country' => $this->request->get('country'),
'state' => $this->request->get('state'),
'city' => $this->request->get('city'),
]);
return $this->generator->generate($name, $parameters, false);
}
public function getName()
{
return 'twig_my_path_extension';
}
}
And as for the configuration its the same as the post
services:
twig.localized_route_extension:
class: Acme\CoreBundle\Twig\PathExtension
tags:
- { name: twig.extension }
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
arguments: [#router]
And for the routes that I use country, state and the city I put them in the prefix to avoid repeating them in each route.
acme_core:
resource: "#AcmeCoreBundle/Controller/"
type: annotation
prefix: /{country}/{state}/{city}
Hope it helps someone else.

Resources