In this namespace you can find everything you need to build and render you HTML components in a safe and comfortable way.
This library wants to give you the guarantee that every time you require an
implementation of the ipl\Html\ValidHtml
Interface you'll not have to worry
about escaping HTML content at all.
- We deal with UTF-8 only. In case you want to handle other encodings, this is not the library you're looking for.
- This library has been written for HTML5
- All our attributes are enclosed with double quotes (
"
)
In case you write code implementing ValidHtml
, you have to follow above rules.
In case you're just using the library, there shouldn't be much to worry about.
We all know, Text needs to be escaped when shipped via HTML, otherwise bad things
(read: XSS) might happen. That's why you need to escape your strings. In PHP
depending on your version you might be used to htmlspecialchars
with a couple
of flags, combined with an encoding.
In case above rules fit your requirements, this should now be as easy as:
<?php
use ipl\Html\Html;
echo Html::escape('This is true: 2 > 1');
The rendered result looks as expected, nothing special so far:
This is true: 2 > 1
Just, we do not want you to even use this escape function. To better explain why, let's add some HTML tags:
<?= Html::tag('h1', 'Hello there!');
<h1>Hello there!</h1>
Alternatively, one might also want to call our magic static helper method like this:
<?= Html::h1('Hello there!');
This looks better and has the same effect, at the disadvantage that your PHP IDE might not understand your code. Let's move on and try to inject some special characters:
<?= Html::tag('h1', 'Hello <> world!');
<h1>Hello <> world!</h1>
As you can see, the content has been escaped. You can also add an Array with multiple strings:
<?= Html::tag('h1', ['Hello', '<name>', 'out' ,'there!']);
Escaping is fine...
<h1>Hello<name>outthere!</h1>
...but we are missing some spaces. Of course we could add them to our strings,
but we can also tell the HtmlElement
to separate it's content with a special
character:
<?= Html::tag('h1', ['Hello', '<name>', 'out' ,'there!'])->setSeparator(' ');
<h1>Hello <name> out there!</h1>
Much better, isn't it? You can separate with any kind of string you want:
<?= Html::tag('h1', ['Hello', 'out' ,'there!'])->setSeparator(' * ');
<h1>Hello * out * there!</h1>
Optionally you might want to pass some attributes:
echo Html::tag('p', ['class' => 'error'], 'Something failed');
<p class="error">Something failed</p>
Attributes and no content is also fine:
<?= Html::tag('ul', ['role' => 'menu']);
<ul role="menu"></ul>
It's perfectly legal to use any ValidHtml
element as content:
<?= Html::tag('ul', ['role' => 'menu'], Html::tag('li', 'A point'));
<ul role="menu"><li>A point</li></ul>
Want to pass multiple elements at once? Use an Array:
<?= Html::tag('ul', ['role' => 'menu'], [
Html::tag('li', 'First point'),
Html::tag('li', 'Second point'),
Html::tag('li', 'Third point'),
]);
<ul role="menu"><li>First point</li><li>Second point</li><li>Third point</li></ul>
You can mix HTML and non-HTML components:
<?= Html::tag('p', [
'Hi ',
Html::tag('strong', 'there'),
', are you ok?'
]);
This works fine:
<p>Hi <strong>there</strong>, are you ok?</p>
Let's once again pick our Menu example. What I do not like about it is that it
forces me to write Html::tag('li', $value)
multiple times. That's why we
introduced the Html::wrapEach()
helper method:
<?= Html::tag('ul', ['role' => 'menu'], Html::wrapEach($list, 'li'));
Now with $list = ['First point', 'Second point', ...]
we get the same output
as we did before.
You can provide a custom callback instead of a tag name to Html::wrapEach()
:
$options = [
'jd' => 'John Doe',
'pp' => 'Purple Princess',
'su' => 'Some User',
];
$select = Html::tag('select', Html::wrapEach($options, function ($name, $value) {
return Html::tag('option', [
'value' => $name
], $value);
})->setSeparator("\n"))->setSeparator("\n");
Guess what? It looks as expected:
<select>
<option value="jd">John Doe</option>
<option value="pp">Purple Princess</option>
<option value="su">Some User</option>
</select>
Pretty cool and simple, isn't it? And before you start coding: there is no need to implement Forms on your own, we already did so for you!
Still, we do not consider this code being very readable. In case you ever used
printf
, the following might come in useful:
<?= Html::sprintf(
'Hi %s, are you ok?',
Html::strong('there')
);
Hi <strong>there</strong>, are you ok?
Say you've now written your own wonderful widget. It's even so wonderful you want to re-use some of its components in another widget? You're in luck, there's a handy shortcut with which you can easily pass elements from one widget to another.
Let's assume our menu example is a proper widget now and add its entries while transforming them to dashboard tiles:
<?= Html::tag('div', ['class' => 'dashboard'])->addFrom(new Menu(), function ($li) {
return $li->setTag('div');
}); ?>
<div class="dashboard"><div>First point</div><div>Second point</div><div>Third point</div></div>