Is it possible to set the value of a twig template block from PHP code? I'm migrating from a different template engine and I need a bridge to set the value of blocks without using a twig template.
I've just got plain text that I was hoping to assign before I render the template.
If you want to include PHP files inside blocks, I suggest you to create an extension.
Sample
index.php
<?php
require(__DIR__ . '/../vendor/autoload.php');
$loader = new Twig_Loader_Filesystem('./');
$twig = new Twig_Environment($loader, array());
$function = new Twig_SimpleFunction('get_php_contents', function($file, $context) {
ob_start();
include($file); // $context is available in your php file
return ob_get_clean();
}, array('is_safe' => array('html')));
$twig->addFunction($function);
echo $twig->render('test.twig', array('name' => 'Alain'));
test.twig
{% extends 'base.twig' %}
{% block content %}
{{ get_php_contents('contents.php', _context) }}
{% endblock %}
base.twig
<html>
<div>I'm a base layout</div>
{% block content %}{% endblock %}
</html>
contents.php
<?php
echo '<div style="color:red">';
echo "Hello {$context['name']}, it is now: ";
echo date("Y-m-d H:i:s");
echo '</div>';
Result
<html>
<div>I'm a base layout</div>
<div style="color:red">Hello Alain, it is now: 2014-10-28 19:23:23</div>
</html>
Related
I am trying to have my twig templates translated using the Symfony Translator Component and .mo files. I used the i18n extention before but wanted a more reliable approach since locale handling for translations on Windows is a nightmare.
These class functions prepare the translation and template:
/**
* Constructor.
*
* #param string $template_dir
* #param string $locale
* #param string $locale_path
*/
public function __construct($template_dir, $locale, $locale_path)
{
$loader = new Twig_Loader_Filesystem($template_dir);
$this->parser = new TemplateNameParser();
$this->template = new \Twig_Environment($loader);
$this->translator = new Translator($locale);
$this->translator->addLoader('mo', new \Symfony\Component\Translation\Loader\MoFileLoader());
$this->translator->addResource('mo', $locale_path, $locale);
$this->template->addExtension(new TranslationExtension($this->translator));
}
/**
* Render template.
*/
public function render($name,$parameters=[]) {
return $this->template->loadTemplate($name,$parameters)->render();
}
Then i have this template:
<h1>{% trans 'Hello World!' %}</h1>
which throws this error:
Uncaught Twig_Error_Syntax: Unexpected token. Twig was looking for the
"with", "from", or "into" keyword.
Which i get because i am not adding the Twig_Extensions_Extension_I18n extension to twig environment. If i do that, the texts in trans functions are not translated because i am not using the filter as i should. For it to work i need to use the trans filter like so: {{ 'Some text'|trans }}.
Is there a way to make translation work with {% trans 'Some text' %} instead of {{ 'Some text'|trans }}? For example, can i add a custom trans function somewhere in the chain?
Note: I know that {% trans %}Some text{% endtrans %} works, but all my templates already use this syntax {% trans 'Some text' %}, and i would like to prevent having to rewrite everything.
The problem seems to stem from incompatible twig and symfony translator versions. But i am not sure tbh.
In my case, i solved the problem long-term by writing a simple script to replace the incorrect syntax with the correct one in each template file.
foreach (glob("your_template_path/*/*/*.twig") as $filename) {
$content = file_get_contents($filename);
$content = preg_replace_callback('/{% trans "[\s\S]+?" %}/',function($matches) {
$text = str_replace(['{% trans','%}','"'],'',$matches[0]);
return '{% trans %}'.trim($text).'{% endtrans %}';
},$content);
$content = preg_replace_callback('/{% trans \'[\s\S]+?\' %}/',function($matches) {
$text = str_replace(['{% trans','%}',"'"],'',$matches[0]);
return '{% trans %}'.trim($text).'{% endtrans %}';
},$content);
file_put_contents($filename,$content);
}
Maybe that helps someone.
Try this
"{% trans %}Hello World{% endtrans %}!"
I need to include template dynamically in twig template. So the template will included the page that defined in routes.php
I try to concatenate string and variable like this code bellow, but still not working.
routes.php:
$app->get('/home', function ($request, $response, $args) {
$data['page'] = "home";
return $this->view->render($response, 'Home/layout.html', $data);
});
Home/layout.html:
{% include 'Home/_header.html' %}
{% include 'Home/_topbar.html' %}
{% include 'Home/_sidebar.html' %}
{% include 'Home/' ~ data.page ~ '.html' %}
{% include 'Home/_footer.html' %}
Error message:
Unable to find template "Home/.html" (looked into: ../App/Templates) in "Home/layout.html" at line 4.
I found my own solution, but it's not the one i want. So I edited routes.php and layout.html like this:
routes.php:
$app->get('/home', function ($request, $response, $args) {
$data['page'] = "{% include 'Home/home.html' %}";
return $this->view->render($response, 'Home/layout.html', $data);
});
Home/layout.html:
{% include 'Home/_header.html' %}
{% include 'Home/_topbar.html' %}
{% include 'Home/_sidebar.html' %}
{% include template_from_string(page) %}
{% include 'Home/_footer.html' %}
What I want is to send variable that contain name of the template file from routes.php, not the template syntax instead.
You are accessing the wrong variable. You are passing the following to twig,
$data['page'] = "home";
return $this->view->render($response, 'Home/layout.html', $data);
Which means to access the variable page inside twig you would just need to call page and not data.page as the array data is not even passed towards to your template
Which means your template should look like the following
{% include 'Home/_header.html' %}
{% include 'Home/_topbar.html' %}
{% include 'Home/_sidebar.html' %}
{% include 'Home/' ~ page ~ '.html' %}
{% include 'Home/_footer.html' %}
You could actually tell this by yourself when looking at the error message
Unable to find template "Home/.html"
As there is nothing in between Home/ and .html, this mean the variable data.page doesn't exist. I recommend to enable debug mode when developing then u would get an error you are trying to access an undefined variable
I am pretty new to the template engine itself. I am wondering how I could include my css stylesheet using twig as it doesn't render the styles everytime I render it.
index.html including the css stylesheet.
<link href="style.css" rel="stylesheet" type="text/css">
<link href="icomoon/style.css" rel="stylesheet">
index.html showing the data (the data is shown correctly, just the css stylesheet, isn't rendering (or the design is not shown).
{% if sv_query.connect and sv_data.password == 0 %}
<center><img src="images/status/server-online.png"/><br/>Server is online!</center>
<center>Players: <font color=green><b>{{ sv_data.players }}</b></center>
{% elseif sv_data.password == 1 %}
<center><img src="images/status/server-warning.png"></br>The server is passworded (under construction).</center>
{% else %}
<center><img src="images/status/server-offline.png"></br>The server is offline, try again later!</center>
{% endif %}
A basic example of how I render the data. Index.php (twig)
require 'Twig/vendor/autoload.php';
$loader = new Twig_Loader_Filesystem('views');
$twig = new Twig_Environment($loader);
$ip = "127.0.0.1";
$port = "7777";
require("views/samp/samp_query.php");
$query = new SampQuery($ip, $port);
$info = $query->GetInfo();
echo $twig->render('index.html', array (
'sv_query' => $query,
'sv_data' => $info)
);
$query->close();
PS I am not using any plugins or templates engines other than twig as what I am doing right now is pretty basic, I just need to get the stylesheet to function properly, or to be included properly.
Thanks, Patrick!
I have this controller where \Exception is raised (I haven't figured out which SF2 Exception to use yet) upon certain condition. Here is it:
<?php
namespace My\AppBundle\Controller;
use ....
class MyController extends Controller
{
const EXCEPTION_MESSAGE = <<<EOF
My <b>HTML</b>
<br/>
<small>Small phrase</small>
EOF;
public function indexAction()
{
// my logic
if(in_array($data, $array))
throw new \Exception(self::EXCEPTION_MESSAGE);
// the rest of my logic
return ....
}
}
And in app/Resources/TwigBundle/views/Exception/error.html.twig
{% extends '::base.html.twig' %}
{% block body %}
<h2>Error</h2>
<p>{{ exception.message }}</p>
{% endblock %}
The problem is HTML is not rendered when seeing the error page in prod environement.
I tried {{ exception.message|raw }} and also setting autoescape to false as per this answer but it seems to have no effect.
How can I do to make HTML works when displaying the \Exception message in Twig?
Where ever in the code you catch the exception is where it is needed to be added to the array you pass to twig. for example
$vars = [];
try {
$a->indexAction();
//fill $vars
} catch (Exception $e) {
$vars['exception'] = $e;
}
//pass $vars to twig
This could sound a bit weird, but this is a special situation:
I have an HTML string in $content, and I want to render a stylesheet block in the head tag of this content. This is what I have:
$response = new Response();
$response->setContent($content);
$response->headers->set('Content-Type', 'text/html');
// returns the HTTP headers followed by the content
return $response;
and I want to add:
{% stylesheets output='compiled/css/*.css' 'css/all.less' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
Any idea of how could achieve it?
Edit:
As #CarlMarkham suggested, I tried:
$loader = new \Twig_Loader_Array(array(
'index.html' => $content."{% stylesheets output='compiled/css/*.css' 'css/all.less' %}
<link rel='stylesheet' href='{{ asset_url }}' />
{% endstylesheets %}",
));
$twig = new \Twig_Environment($loader);
return $twig->render('index.html');
but I got this error:
Unknown tag name "stylesheets" in index.html
Also tried this:
$loader = new \Twig_Loader_Array(array(
'index.html' => $content.'<link rel="stylesheet" href="{{ asset("compiled/css/*.css") }}">'
));
$twig = new \Twig_Environment($loader);
return $twig->render('index.html');
but I got:
The function "asset" does not exist in index.html
Take a look at Assetic. You should be able to build the html from within php (first code block click on the php tag). That example is for JS but it is the same concept for CSS. Now you have the string you can add it to the content.