XHP: A New Way to Write PHP

By Marcel Laverdet on Tuesday, February 9, 2010 at 3:59pm

Today, I'd like to take to this opportunity to share with you a project that's quickly becoming a cornerstone of front-end PHP development at Facebook. XHP is a PHP extension which augments the syntax of the language to both make your front-end code easier to understand and help you avoid cross-site scripting attacks.

XHP does this by making PHP understand XML document fragments, similar to what E4X does for ECMAScript (JavaScript). While PHP is typically used to write front-end code, by itself it isn't a very good language for generating HTML (as evidenced by the popularity of templating engines like Smarty). XHP is something between a programmatic UI library and a full templating system.

PHP has some tricks up its sleeve like the ability to switch between HTML and PHP syntax, but this often encourages poor security practices and hard to follow control flows. Consider this simple PHP application:

<?php
if ($_POST['name']) {
?>
<span>Hello, <?=$_POST['name']?>.</span>
<?php
} else {
?>
<form method="post">
What is your name?<br>
<input type="text" name="name">
<input type="submit">
</form>
<?php
}

This demonstrates using PHP open and close tags to generate HTML, in addition to the inline expression syntax. Despite being a very simple example, it can be difficult to follow the code as you switch in and out of PHP and HTML. You could forgo the PHP/HTML context switches and just use echoes, but you're still left with the likelihood of introducing a vulnerability.

Furthermore, this example has a security hole; the raw use of $_POST here has opened us up to a cross-site scripting attack. The correct solution is to pass this input through htmlspecialchars() before displaying it to the user. This is a poor way to develop applications, though as it makes a secure application the exception, rather than the default.

Here is the same application written using XHP:
<?php
// note: includes omitted
if ($_POST['name']) {
echo <span>Hello, {$_POST['name']}</span>;
} else {
echo
<form method="post">
What is your name?<br />
<input type="text" name="name" />
<input type="submit" />
</form>;
}

The first thing you may notice is that this application is a little bit easier to follow when you get rid of the PHP tags muddling up the code. Take note of the echo statements; this application demonstrates some new syntax that XHP has added to PHP. What's important is that we are not echoing raw strings to the user; this is inline XML. XHP gives PHP the ability to understand XML as if it were native to PHP. What's interesting about this is that now PHP has context-specific information about what you're doing with $_POST. It knows that $_POST is being used as HTML (PCDATA) and can escape it automatically. What we've done here is made security the default.

Baking XML into the PHP syntax yields some other advantages which may not be obvious at first. Probably the coolest is that errors in your markup will now be detected on the server at parse time. That is, it is impossible to generate malformed webpages while using XHP. This helps prevent bugs when different browsers parse malformed markup in different ways. Also, instead of directly echoing these elements, you can store them as PHP references and use them later; each XHP node is actually an instance of an object. This helps with functional decomposition, as you can pass these references around and mutate them similarly to the way you mutate the DOM in JavaScript.

One last feature of XHP, which has been invaluable to us at Facebook, is that you can define your own elements which can condense a complex component into a simple XHP tag. XHP has a rich collection of declarations which let you define new elements, configure their expected attributes, as well as describe their content model. These features turn XHP into a powerful templating engine which is capable of simplifying complicated pages into easy to read high-level markup, but it's up to you to create your own elements from the primitives that XHP defines.

XHP has enabled us to build better websites faster; our Lite site was written entirely with XHP. Try XHP out for yourself.

You can grab XHP on GitHub and after that, check out the documentation for more information on using XHP.

Marcel, a Facebook engineer, may or may not have broken Facebook several times while developing this software.