mindplay/escape
This package provides a small set of global functions for use in plain PHP templates., (*1)
, (*2)
I use this with kisstpl and plain PHP templates, but
any package (or plain, raw PHP scripts) should be fine., (*3)
It's really more documentation (perhaps even more just a philosophy) than it is code - and includes detailed
inline documentation with examples., (*4)
These are just tiny shorthand-functions wrapping htmlspecialchars() and json_encode() but
with the assumption that you always want HTML 5 and UTF-8 encoding - if you don't,
this package is not for you., (*5)
The source-file is bootstrapped to aggressively autoload via Composer, which
means these functions are always available, without having to use require or include., (*6)
Currently the following functions are included:, (*7)
-
html($value) ~ htmlspecialchars((string) $value, ENT_HTML5, 'UTF-8', true)
-
attr($value) ~ htmlspecialchars((string) $value, ENT_QUOTES | ENT_HTML5, 'UTF-8', true)
-
js($value) to escape inside a JavaScript string-literal context
-
json($value) ~ json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
Note that, because these functions are global, the addition of any new function would be considered a breaking
change with a major version number increase., (*8)
Why?
Because the PHP defaults for these functions are outdated., (*9)
And why global? Because we can't autoload functions, importing namespaced functions in every
template is a hassle, and we're not using the global namespace for anything anyway., (*10)
Escaping and Encoding Values
Each function is intended for use within a single context - e.g. within an HTML tag, an
HTML attribute-value, a Javascript string literal, or inline in Javascript code. (Note that
contexts are often nested, as per the examples in the "Nested Contexts" section below.), (*11)
This is best illustrated with a few common examples., (*12)
When outputting a string value in the context of an HTML tag, use the html() function:, (*13)
<h1><?= html($title) ?></h1>
HTML Attributes
When outputting a string value in the context of an HTML attribute, use the attr() function:, (*14)
<div id="<?= attr($id) ?>">
Javascript
The following examples assume a pure JSON or Javascript context, e.g. a template emitting content
for a response with a Content-Type of application/json or application/javascript - contrast
this with a nested context, such as Javascript inside a <script> tag., (*15)
When outputting a JSON-compatible (string, int, float, bool, null or array) value
in the context of JSON or Javascript code, use the json() function:, (*16)
function welcome() {
alert(<?= json($message) ?>);
}
When outputting a string in the context of a Javascript string literal, use the js() function:, (*17)
function welcome() {
alert('Welcome, <?= js($username) ?>');
}
Notice the difference: json() will add quotes when given a string value, whereas js() assumes
you're outputting string content between quotes., (*18)
Nested Contexts
For security reasons, it's important to always consider the context within which you're outputting content -
and helpful to think of some contexts as being nested within a different context., (*19)
The most common example of nested context is a <script> tag embedded in an HTML context - for example:, (*20)
<script>
function welcome() {
alert(<?= html(json($message)) ?>);
}
</script>
In this example, the inner context is Javascript code, and the outer context is HTML - so the inner
function call is json() and the outer function call is html()., (*21)
Another example is a JavaScript string-literal context inside an HTML attribute:, (*22)
<button onclick="alert('Hello, <?= attr(js($username)) ?>')">
In this example, the inner context is a Javascript string literal, and the outer context is an HTML-attribute., (*23)
There are many possible use-cases combining two (or more) contexts - but if you can wrap your head around the
idea of nested contexts, selecting the right combination of functions should be fairly easy., (*24)