Getting PHP to make the HTML for me

by Derek Sivers

Earlier I pointed at the essays by Paul Graham about building up a language, and that guy that made Ruby Rails.

Now that I'm making my own HTML template system, I realize what I need are functions, as if built into PHP, that will do some basic HTML markup of strings.

h1, h2, h3, h4, h5
p div span
ul li
dl dd dt
table tr td
code address pre blockquote
a href
form input select option label

All of those tags can (and will often) have one or more these attributes:

Also, image and a href have their own special targets. And forms have their own special attributes.

Somewhere in Ruby-love I got it in my head that everything should be an object.
But what I want here are functions that returns a result:

div('hello') = <div>hello</div>
div('hello', 'id', 'greeting') = <div id="greeting">hello</div>

PHP already has a bunch of these under "String Functions". Some great ones are:
htmlentities('"you & me"') = &quot;you &amp; me&quot;
strip_tags('<a href="me.html">me</a>') = me
strtoupper('hello') = HELLO

So there we go. If I could alter the language itself to add these functions, I would. (Yes OK I know I could write modules in C to expand PHP, but I'd hate for someone else to have to maintain or debug that.)
So I think the best thing is to write a library of string-altering functions.

How to do the attributes, though? The best way I've ever seen is PHP's XML DOM class:

$track = $tracks->new_child('amount', 10) = <amount>10</amount>
$track = $tracks->new_child('amount', 10);
$track->set_attribute('currency', 'USD') = <amount currency="USD">10</amount>

If I were to do that with HTML-markup objects, it'd have to look like this, though:
$x = $html->div('hello');
$x->attribute('id', 'greeting');
$x->attribute('title', 'welcome');
= <div id="greeting" title="welcome">hello</div>
Hmmmmmmmmm......... That's not very elegant for use in a hundred places on an HTML page.

What if attribute() was also a string-altering function that uses a little regex to add an attribute to the first HTML tag it sees?
$plaindiv = div('hello') = <div>hello</div>
$div_plus_class = attribute($plaindiv, 'class', 'greeting') = <div class="greeting">hello</div>
attribute($div_plus_class, 'title', 'welcome') = <div title="welcome" class="greeting">hello</div>

Ooh! The nice thing about this is that I could use, say, a table-making function, to get me back a table:
$mytable = table($bigarray);
... then add an id to the table afterwards like this:
attribute($mytable, 'id', 'sales') = <table id="sales"><tr><td>etc...</td></tr></table>

Yeah I'm diggin' this.

Holy shit I just went to go test this idea and it took only 30 seconds, and seems to work!

# regex to add an attribute to an HTML opening tag
function attribute($html, $key, $value)
$pattern = '/^<(\w+)/ ';
$replace = '<$1 ' . $key . '="' . $value . '"';
return preg_replace($pattern, $replace, trim($html));


2004-05-13 03:16:45
useful prior art
Your system sounds similar to Donovan Preston's Nevow.Stan HTML generator (part of his Nevow templating system for Python). Here's a link if you want to compare for ideas:

(Obligatory self-plug: if you want a good templating engine design to steal, feel free to nick mine: HTMLTemplate)

2004-05-13 13:59:52
derek your driven

nice to see your still plugging away. David Hooper jokingly introduced me to you as his 'guru' while we were all standing in line at some noodle house on Haight St. in SF, CA some years ago. Any way . . .

I think its really awesome that your taking this on, but I've gotta ask, have you evaluated any of the other php template engines available? Or are you doing this as a learning experience? Hopefully you can stand on the shoulders of others to a certain extent rather than reinventing the wheel.


PS Man throw the "Hit Me" stuff up into the iTunes music store . . . passive residual income to dedicate to other causes :-)

2004-05-13 14:12:11
don't forget validation
I've been thinking about the same path, although a more limited tool for making forms for me. Something to not forget is client and server side validation, the form making script may as well make that stuff too. Coldfusion has had some of this stuff for a while now with its cfform tags.
2004-05-13 14:57:03
As a musician/programmer, let me suggest the deceptively simple yet wonderfully effective PHP template class found in the PHPLIB package (file: Goto:
2004-05-14 01:07:35
Thanks for the comments - please see next post first, though.
Thanks for your comments, everyone. They made me realize that I wasn't explaining myself well.

Please read my next post, called I don't want templates, I want HTML-making shortcuts. Then this stuff above will make more sense.