I have implemented a new twig extension and I have some text which had to be translated.
Unfortunately when I use a code label it appears as a sample text.
I mean when twig render this following extension, it displays: 5 entity.years instead of 5 years for example:
class MyExtension extends \Twig_Extension {
public function getFilters()
{
return array(
'myextension' => new \Twig_Filter_Method($this, 'myextension'),
);
}
public function myextension ($myId)
{
// ....
// Some operations concerning $myId...
// ....
if($myId!=0) {
$res = $myId. ' '.'entity.year';
} else {
$res = ($months == 0 ? $days.'entity.days' : $months.'entity.months');
}
return $res;
}
}
Where entity.years, entity.months, entity.days is defined into my translations folder.
Inject the translator service into your extension and use it. For example:
class MyExtension extends \Twig_Extension
{
private $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
// ...
public function myMethod()
{
return $this->translator->trans('my_string');
}
}
Related
Is there a way to add a div to body when the Widget is rendered? Like using a hook 'wp_body_open' or something.
Where can I put a hook in Widget_Base extended class for it?
I'm using a common Class like:
use Elementor\\Widget_Base;
use Elementor\\Controls_Manager;
class MenuHamburguer extends Widget_Base
{
public function __construct($data = [], $args = null)
{
parent::__construct($data, $args);
// I've tried here, but no success.
}
public function get_name()
{
return 'menu-hamburguer';
}
public function get_title()
{
return __('Menu Hamburguer', 'later');
}
public function get_icon()
{
return 'fa fa-bars';
}
public function get_categories()
{
return ['later'];
}
protected function _register_controls()
{
// do normal stuff of the widget...
}
protected function render()
{
// do normal stuff of the widget...
}
}
I'd like my bundle to inject a twig global from its config.
class MyBundle extends AbstractBundle
{
public function build(ContainerBuilder $container): void
{
parent::build($container);
$container->addCompilerPass(new TwigPass());
}
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$theme = $config['theme']; // how to make this a twig global?
// $twig = $builder->getDefinition('twig'); // NOPE! Twig isn't loaded yet.
}
The compiler pass gets twig, which isn't available when my bundle extension is loading.
class TwigPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition('twig')) {
return;
}
$theme = 'theme_from_config';
$def = $container->getDefinition('twig');
$def->addMethodCall('addGlobal', ['theme', $theme]);
I'm missing something, or something is out of order. How can the compiler pass get the config data from the extension? Or if that's not the right approach, how can I inject a twig global from my bundle config?
The way to make config data available to a pass is to add the data to the container as a parameter:
class TwigPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition('twig')) {
return;
}
$theme = $container->getParameter('my.theme');
$def = $container->getDefinition('twig');
$def->addMethodCall('addGlobal', ['theme', $theme]);
}
}
class CeradMyBundle extends AbstractBundle
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$container->parameters()->set('my.theme', $config['theme']);
}
To actually get your theme config value into the $config array requires making a Configure class. Fortunately AbstractBundle can simplify this with a configure method:
# config/packages/cerad_my.yaml
cerad_my:
theme: theme_from_config_file
class CeradMyBundle extends AbstractBundle
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->scalarNode('theme')->defaultValue('theme_default')->end()
->end()
;
}
After getting this to work, it was a tiny bit annoying to have that one extra DI class i.e. TwigPass so I stole a trick from the Kernel and just had the AbstractBundle implement the pass interface:
class CeradMyBundle extends AbstractBundle implements CompilerPassInterface
{
public function build(ContainerBuilder $container): void
{
// Register as a pass
$container->addCompilerPass($this);
}
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$container->parameters()
->set('my.theme', $config['theme']);
}
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->scalarNode('theme')->defaultValue('theme_default')->end()
->end()
;
}
// The compiler pass
public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition('twig')) {
return;
}
$theme = $container->getParameter('my.theme');
$def = $container->getDefinition('twig');
$def->addMethodCall('addGlobal', ['theme', $theme]);
}
}
If you follow this approach then you can actually save your theme as a property in your bundle class and avoid the need to add a public parameter. Your choice.
I have a problem with binding params. My code is:
interface MessageInterface
{
public function getMessage() : string;
}
class MessageType1 implements MessageInterface
{
public function getMessage(): string
{
return 'Type 1';
}
}
class MessageType2 implements MessageInterface
{
public function getMessage(): string
{
return 'Type 2';
}
}
class TestController extends AbstractController
{
private $m;
public function __construct(MessageInterface $m)
{
$this->m = $m;
}
/**
* #Route("/message", name="message")
*/
public function index(MessageInterface $m): Response
{
return $this->render('test/index.html.twig', [
'message' => $m->getMessage(),
]);
}
}
How to bind in service.yaml TestController constructor param to MessageType1 class and method index param to MessageType2 class ?
How can definition a global variable for use in all function controller
class TestController extends Controller
{
private $x;
public function index()
{
$this->$x ='22';
}
public function send_message()
{
echo $this->$x;
}
}
Write $this->x rather than $this->$x
class TestController extends Controller
{
private $x;
public function index()
{
$this->x ='22';
}
public function send_message()
{
echo $this->x;
}
}
If you want to make global variable in controller, the following code will work definitely:
private $x = 22;
public function index()
{
print_r($this->x);
die();
}
I need to get a parameter value in my following twig extension class
namespace xxxx\WebBundle\Twig;
use Symfony\Component\HttpKernel\KernelInterface;
class MyExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('affliate', array($this, 'urlFilter')),
);
}
public function urlFilter($url,$aff)
{
$separator = "?";
if (strpos($url,"?")!=false) {
$separator = "&";
}
$parse = parse_url($url);
//echo $parse['host'];
$app_url = $url.$separator.'tag='.$aff;
return $app_url;
}
public function getName()
{
return 'wishbot_extension';
}
}
In controller we can use like this $this->container->getParameter('contact_email');
But I need the value in twig extension class.
Inject the parameters as arguments into your twig extensions's constructor like this:
config.yml
services:
twig.extension.your_extension:
class: Vendor\YourBundle\Twig\Extension\YourExtension
arguments: [ %parameter1%, %parameter2% ]
tags:
- { name: twig.extension }
YourExtension.php
protected $parameter1;
protected $parameter1;
public function __construct($parameter1, $parameter2)
{
$this->parameter1 = $parameter1;
$this->parameter2 = $parameter2;
}
// ....
public function urlFilter($url,$aff)
{
// access the parameters using $this->parameter1
}