Unescape or html decode in Twig (PHP Templating)
You can use the raw
filter to make twig render raw html
http://twig.sensiolabs.org/doc/filters/raw.html
{% autoescape %}
{{ var|raw }} {# var won't be escaped #}
{% endautoescape %}
Decode HTML entities stored in MySQL with Twig (in Symfony)
Carefully control encodings.
The problem you are encountering is the simplest form of the nightmare that is character encoding. Rule one in handling encoding issues is to always control the encoding. In your case, this HTML should really be stored un-encoded in the DB, allowing for a single use of the twig raw
output filter.
Consider the implications if you don't know whether the HTML needs to be decoded. For instance, if someone intended to show a <
(<
) in the text, and the html wasn't encoded, then applying html_entity_decode
will turn that encoded <
into a real one, and break the HTML. (Browsers will think you're starting a new TAG).
Forms submitting html
I'm going to guess that elsewhere in your app, there are forms which allow people to submit HTML. HTML forms encode data before posting, PHP $_POST
handling usually auto applies htmlentities
onto posted fields.
Whatever methods of your application are handling the storing of such Posted HTML, or add/changes these entities, should use html_entity_decode
to ensure it is stored as raw html.
This way, you always know that HTML is stored in you database in exactly the state it needs to be rendered on the page. If it needs to be encoded and decoded again somewhere for some reason, you're not left hoping that some of the content won't be double-decoded. (Or as in your case, missing a decode step and spitting out raw HTML).
Rendering HTML in twig
One way or another, you need to get that content to your twig, passed through the raw
filter, in the exact state it needs to be put on the page. While this can be done in twig, or with twig functions, this really should be done in the Controller.
Consider that path this data is traveling:
- Form (raw HTML)
- PHP POST (encoded HTML)
- DB (encoded HTML)
- SELECT Query
- PHP Controller (encoded HTML)
- Twig
- Rendered HTML
The earlier you can get the data in the correct state, the better. Doing so makes the data easier to work with, reduces the performance impact, and prevents code-duplication later in those steps. (What happens if you want to use this html in other Controllers or Twig templates? Code duplication.) Hense, my first suggestion to get it in the database cleanly.
If clean data is not an option...
Clean the data in your controller, maybe even with a static function in the entity.
The only other clean-ish way to handle this, is to loop through and decode the html before passing it to Twig. Doing it this way however, or later in the Tiwg template as you're currently doing, you run the risk of double-decoding that I mentioned earlier.
Veille
Class Veille
{
. . .
public static function decodeArray(?array $vielleList): ?array
{
foreach ($vielleList as $vielle) {
if (!$vielle instanceof self) {
continue;
}
$vielle->setVText(html_entity_decode($vielle->getVText()));
}
return $vielleList;
}
public function getVText(): ?string
{
return htmlentities("<h3>Encoded HTML Test</h3>Good data > parsing bad data.");
}
public function setVText(?string $text): void
{
}
}
Controller
$listactufree = $repository->findBy(
array('vStatus' => '4'), // Critere
array('vDatePublished' => 'desc'), // Tri
5, // Limite
0 // Offset
);
$listactufree = Veille::decodeArray($listactufree);
Twig
{% for veille in listactufree %}
{{ veille.vTexte|raw }}
{% endfor %}
Note, this same code could clean your data.
Plugging the contents of the decodeArray
method into a command, and running that command, along with persist/flush, would store decoded HTML for all of your entities. Just make sure you only decode ONCE, and any methods which can add or edit these entities store the HTML unencoded. That's the key. Unencoded data.
How to escape entire block with html-entities via twig?
Twig does not by default escape template markup. If you wish to escape your HTML in this way, then set it to a variable first and then either autoescape
it, or use a regular escape
:
<rawXml>
<message>
{% set myHtml %}
<ThisShouldBeEscaped>
<ButItIsnt>Dang</ButItIsnt>
</ThisShouldBeEscaped>
{% endset %}
{% autoescape 'html' %}
{{ myHtml }}
{% endautoescape %}
<!-- or -->
{{ myHtml|escape }}
</message>
</rawXml>
Twig doesn't render html tags, |raw doesn't work
I don't know why you have <p>Lorem ipsum</p>
as HTML content in your database, since it is NOT HTML, it is escaped HTML. Using raw
unescapes the content, so your escaped HTML becomes... wait for it... HTML. And since twig escapes automatically HTML, that's why tags are displayed on your page.
What you could try as a quick fix is {{post.text|raw|raw}}
to unescape the unescaped HTML. But honestly, what I would recommend for the sanity of your application is to unescape the HTML directly in your database. You SHOULD have <p>Lorem ipsum</p>
in your database, then using {{post.text|raw}}
should work perfectly.
html_entity_decode for twig (opencart)
Just register the html_entity_decode
function in twig
.
The most simple way is to look where twig
is loaded and add the following code,
$twig->addFilter(new \Twig_Simple_Filter, 'html_entity_decode', 'html_entity_decode');
After that you can just do the following in your twig
templates
{{ attribute.text|html_entity_decode }}
UPDATE: For Opencart 3.0.3.7 version filter should be like this:
$twig->addFilter(new \Twig\TwigFilter('html_entity_decode','html_entity_decode'));
Related Topics
How to Select Rows Where Column Value Is Not Null Using Codeigniter's Activerecord
Check If Laravel Model Got Saved or Query Got Executed
Best Way to Internationalize Simple PHP Website
Get All Defined Classes of a Parent Class in PHP
Escaping/Encoding Single Quotes in JSON Encoded HTML5 Data Attributes
Multi-Byte Safe Wordwrap() Function for Utf-8
Mysql/SQL Retrieve First 40 Characters of a Text Field
Add a Quantity Field to Ajax Add to Cart Button on Woocommerce Shop Page
Replacing Variables in a String
Dynamic Comparison Operators in PHP
How to Make 5 Random Numbers with Sum of 100
How to Get MySQL 8 to Run with Laravel
What's the Difference Between Is_Null($Var) and ($Var === Null)