Extend Twig with variables - php

I use Twig and I have a header in each file with some variables.
How I can include the header in each file without always calling the variables ?
I've a file, in it, I extends the layout.html.twig and in this layout I extends the header.html.twig
on the header I've some variables sent by the controller. but the variables are executed only if I go to the header view...
How can I do to include the header view with twig?

Despite the fact that is really difficult to understand what exactly you're after, probably, you're looking for a way to set global variables.
Twig globals allows you to set global variables.
Set static variables:
# app/config/config.yml
twig:
# ...
globals:
variables: {}
If you need more than static variables, create your own extension:
<?php
namespace Example\CommonBundle\Twig;
use \Doctrine\ORM\EntityRepository;
class TooltipsExtension extends \Twig_Extension
{
protected $bookingsTooltip;
public function __construct(EntityRepository $bookingsTooltip)
{
$this->bookingsTooltip = $bookingsTooltip;
}
public function getGlobals()
{
return array(
'tooltips' => $this->bookingsTooltip->getTooltips(),
);
}
public function getName()
{
return 'tooltips';
}
}
Register twig extension:
# app/config/services.yml
example.tooltips_extension:
class: Example\CommonBundle\Twig\TooltipsExtension
public: false
arguments:
- #example.tooltips
tags:
- { name: twig.extension }
Access variables inside your html:
{{ dump(tooltips) }}

Related

Symfony 4, get .env parameter from a controller, is it possible and how?

From symfony 4, I want create a global parameter and get the value of this parameter from a controller.
This parameter is the path of an another app in the server. So, I thinked add the paramerter in the .env file. But how can I get the value of this parameter from a controller?
For Symfony 5
in your .env file
APP_PARAM=paramvaluehere
in your config/services.yaml
parameters:
app.paramname: '%env(APP_PARAM)%'
in your controller
$this->getParameter('app.paramname');
If someone is stil looking for a quick fix but not much symfonish,
define your parameter in .env
MY_PARAM='my param value'
and then in controller call it
echo $_ENV['MY_PARAM'];
if you call the varaible in the controller you better define it in the config/services.yaml under parameters section and access it through parameterBag is much symfonish way.
Did you try with:
$this->getParameter('your parameter');
Edit:
This may help you -> https://symfony.com/doc/current/components/dotenv.html
Before to user getParameter() you have to add this in services.yaml
parameters:
your_parameter: '%env(your_parameter)%' # from .env file
Add the variable in the config parameters :
parameters:
your_variable: '%env(YOUR_ENV_VARIABLE)%'
Fetch it from the controller
$var = $this->getParameter('your_variable');
Yes it is. You have 03 steps configuration : Filstly - declare yours variables in env. Secondly - configure service file and finally - call your parameter in your controller :
_ In controllers extending from the AbstractController, use the getParameter() helper :
YAML file config
# config/services.yaml
parameters:
kernel.project_dir: "%env(variable_name)%"
app.admin_email: "%env(variable_name)%"
In your controller,
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class UserController extends AbstractController
{
// ...
public function index(): Response
{
$projectDir = $this->getParameter('kernel.project_dir');
$adminEmail = $this->getParameter('app.admin_email');
// ...
}
}
_ If controllers not extending from AbstractController, inject the parameters as arguments of their constructors.
YAML file config
# config/services.yaml
parameters:
app.contents_dir: "%env(variable_name)%"
services:
App\Controllers\UserController :
arguments:
$contentsDir: '%app.contents_dir%'
In your controller,
class UserController
{
private $params;
public function __construct(string $contentsDir)
{
$this->params = $contentsDir;
}
public function someMethod()
{
$parameterValue = $this->params;
// ...
}
}
_ Finally, if some controllers needs access to lots of parameters, instead of injecting each of them individually, you can inject all the application parameters at once by type-hinting any of its constructor arguments with the ContainerBagInterface:
YAML file config
# config/services.yaml
parameters:
app.parameter_name: "%env(variable_name)%"
In your service,
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
class UserController
{
private $params;
public function __construct(ContainerBagInterface $params)
{
$this->params = $params;
}
public function someMethod()
{
$parameterValue = $this->params->get('app.parameter_name');
// ...
}
}
source Accessing Configuration Parameters
In Symfony 4.4 this works fine:
<?php
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
class SomeController extends AbstractController
{
public function someMethod(Request $request)
{
$parameterValue = $request->server->get('env_varname');
// ...
}
}
also in TWIG:
{{ app.request.server.get('env_varname') }}

Twig can't find function created inside TwigExtension class

I am trying to call Twig function created in TwigExtension (Symfony 3.3). Problem is that I can't find what I did wrong and I am not sure why it is not working
Does someone knows where is the problem?
This is error I am getting:
Unknown "getCurrentLocale" function.
Here is my code:
Twig Extension:
<?php
namespace AppBundle\Extension;
use Symfony\Component\HttpFoundation\Request;
class AppTwigExtensions extends \Twig_Extension
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('getCurrentLocale', [$this, 'getCurrentLocale']),
];
}
public function getCurrentLocale()
{
dump ($this->request);
/*
* Some code
*/
return "EN";
}
public function getName()
{
return 'App Twig Repository';
}
}
Services:
services:
twig.extension:
class: AppBundle\Extension\AppTwigExtensions
arguments: ["#request"]
tags:
- { name: twig.extension }
Twig:
{{ attribute(country.country, 'name' ~ getCurrentLocale() ) }}
So what is your overall plan with the extension. Do you still need it when app.request.locale in twig returns the current locale? (which it does)
Also by default the #request service does not exist anymore.
In Symfony 3.0, we will fix the problem once and for all by removing the request service — from New in Symfony 2.4: The Request Stack
This is why you should get something like:
The service "twig.extension" has a dependency on a non-existent service "request".
So you made this service? Is it loaded? What is it? You can see all available services names matching request using bin/console debug:container request.
If you do need the request object in the extension, if you are planning to do more with you would want to inject the request_stack service together with $request = $requestStack->getCurrentRequest();.
Somehow the code, symfony version and the error message you posted don't correlate. Also in my test, once removing the service arguments it worked fine. Try it yourself reduce the footprint and keep it as simple as possible, which in my case was:
services.yml:
twig.extension:
class: AppBundle\Extension\AppTwigExtensions
tags:
- { name: twig.extension }
AppTwigExtensions.php:
namespace AppBundle\Extension;
class AppTwigExtensions extends \Twig_Extension {
public function getFunctions() {
return [
new \Twig_SimpleFunction('getCurrentLocale', function () {
return 'en';
}),
];
}
}
And take it from there, figure out when it goes wrong.

How call method from service container in config in Symfony?

I have some variables in twig-templates, so think use global scope for it.
config.yml
twig:
globals:
varA: "#wf.autoload.getA"
varB: "#wf.autoload.getB"
In service yml I have:
services.yml
wf.autoload:
class: Scope\WfBundle\WfAutoloadService
arguments: ["#doctrine.orm.entity_manager"]
WfAutoloadService class have public function for getting variables
class WfAutloadService {
...
public function getA(){
return ...;
}
public function getB(){
return ...
}
...
}
My idea doesn't work. Method of #=service(wf.autoload).getA() also doesn't work.
Is it possible? Or it bad idea and bad practice?
Thanks
If getA() and getB() returns object, you can use a factory when configuring your service:
services:
wf.autoload:
class: Scope\WfBundle\WfAutoloadService
arguments: ["#doctrine.orm.entity_manager"]
wf.autoload.getA:
class: A
factory: ["#wf.autoload", getA]
And set the global twig:
twig:
globals:
varA: "#wf.autoload.getA"
I you want to use this functions in many twig templates you can create a twig extension
For example :
class MyExtensions extends \Twig_Extension
{
public function getFunctions()
{
return array(
'getA' => new \Twig_Function_Method($this, 'getA', array('is_safe' => array('html')))
);
}
public function getA() // you can if you want pass parameters
{
//your code
return ...
}
}
Declare it as service :
myextensions.twig_extension:
class: Project\YourBundle\Twig\MyExtensions
public: false
tags:
- { name: twig.extension }
And call it in yours twig template :
{{ getA() }}

Call controller or view (twig file) from self defined twig extension in smyfony2

i've got a problem in symfony2 at the moment and i don't know how i can solve it.
Within a self defined new twig extension I want to call a controller or or a view (a twig file).
How is the correct way to realize this? Can you help me? I've read many symfony2 internet pages but i didn't found a good programming approach for me.
For better understanding why i want to do something like this, here is an exmaple what is my idea:
I want to source out some html code into an separate view. This new view is embedded in another view by calling the twig extension.
So how can i realize this?
Thanxs for your help.
As you are using Symfony2, you can inject the templating service to your Twig extension and then call the ->render method.
The extension
<?php
namespace YourPackage\YourBundle\Twig\Extension;
use Symfony\Component\Templating\EngineInterface;
class Test_Extension extends \Twig_Extension
{
protected $templating;
public function __construct(EngineInterface $templating)
{
$this->templating = $templating;
}
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('my_test', array($this->myTest()), array('is_safe' => array('html')))
);
}
public function myTest()
{
// do some stuffs
$data = $this->templating->render("SomeBundle:Directory:file.html.twig");
// ...
return $data;
}
public function getName()
{
return 'test';
}
}
services.yml
# src/YourPackage/YourBUndle/Resources/config/services.yml
services:
test.test_extension:
class: YourPackage\YourBundle\Twig\Extension\TestExtension
arguments: ['#templating']
tags:
- { name: twig.extension }

How do I declare a function that is available globally across all Twig templates in a bundle?

My question is pretty simple: How can I write a function once and make it available globally across every Twig template I have in a bundle?
Try to reproduce more or less the following class in Bundle\Twig\Extensions
class LabelsExtension extends \Twig_Extension
{
function getName()
{
return 'labels';
}
function getFunctions()
{
return array(
'perso_label' => new \Twig_Function_Method($this, 'persoLabel')
);
}
function persoLabel($value)
{
if ($value == 1) return 'HI';
}
}
Then in your config.yml or services.yml, you need to have something like this:
services:
twig.extension.mynamespace.labels:
class: Namespace\Bundle\Twig\Extension\LabelsExtension
tags:
- { name: 'twig.extension' }
So now you can call it in any template with {{ perso_label(1) }} or whatever.

Categories