Easily formatting dynamic HTML tags in PHP
03 Feb 2012
It's probably somewhat ironic that I'm writing my first code-oriented post about PHP. After all, I'm becoming more of a Rails fanboy the more I learn about it, and putting down PHP is one of my favorite pastimes. That being said, we're about to roll out a Drupal installation over at SexInfo Online, and so at least a cursory knowledge of PHP is required.
So what are we doing here?
I got sick of seeing code that looked like this:
<?php
while($row = mysql_fetch_array($result)){
echo "<div class=\"item\">" . $row['field']; . "</div>";
}
?>
I decided that I needed a utility function similar to Rails' own content_tag method, which allows you to do something like this:
<%= content_tag(:p, "Hello World!", :class => "strong") %>
The function is taking 3 parameters in this case: the type of tag (as a Ruby symbol), the content itself, and optional HTML attributes such as classes or an ID. So let's model our PHP version on this, and write down some sample usage.
// Our end goal:
<?php
$content = "Hello World!";
echo content_tag("p", $content, array("class" => "strong"));
// Should return <p class="strong">Hello World!</p>
?>
Let's go about actually implementing this!
Getting Started
Our first step is to think about the parameters that our content_tag()
method will accept, but we've already covered that. We need to be able to specify the type of tag, the content, and optional attributes. Let's write our basic skeleton.
<?php
function content_tag($tagName, $content, $attr=array()) {
// Implementation later!
}
?>
Nothing too complicated here. The $tagName
and $content
variables will be passed in as strings. Attributes are slightly more tricky; we're giving them a default value of a blank array, and will handle them as key-value pairs when used, e.g., "class" => "strong"
Before we move on and start writing code, let's think about what an HTML tag actually consists of. Take a look at this simple tag:
<p>Hello World!</p>
This is about as simple as it gets. It consists of a the opening tag (<p>
), the content, and the closing tag(</p>
). Already some helper methods are becoming apparent: one each for the opening and closing tag. The methods will be very similar: each one needs to take in a $tag
parameter so that the appropriate tag can be output, but the opening tag also needs to account for possible HTML attributes. Let's start backwards and write the close_tag()
method first.
The close_tag() method
This is simplest helper method we'll be writing. All we need to pass in is the type of tag to be closed!
<?php
function close_tag($tag) {
return "</" . $tag . ">";
}
?>
Not a whole lot to say there. Onwards!
The open_tag() method.
Our job gets a little bit trickier here. The tag itself is very simple, similar to close_tag()
, except that we need to account for HTML attributes as a possible parameter. As I mentioned before, attributes will be handled as key-value pairs in an array. To translate this into HTML, we need to loop through all the pairs in our attribute array and output it as key="value"
. Let's put this in a helper method to prevent our open_tag()
method from getting cluttered, and call it generate_attr_string()
, a function which will take a single array parameter.
<?php
// Example usage: generate_attr_string(array("id" => "nav", "class" => "item"));
//=> id="nav" class="item"
function generate_attr_string($attr) {
$attr_string = null;
if (!empty($attr)) {
foreach ($attr as $key => $value) {
// If we have attributes, loop through the key/value pairs passed in
//and return result HTML as a string
// Don't put a space after the last value
if ($value == end($attr)) {
$attr_string .= $key . "=" . '"' . $value . '"';
} else {
$attr_string .= $key . "=" . '"' . $value . '" ';
}
}
}
return $attr_string;
}
?>
That's a little ugly, but it makes our open_tag()
method trivial to finish. Let's wrap that up.
<?php
// Example usage: open_tag("p", array("id" => "nav", "class" => "item"));
//=> <p id="nav" class="item">
function open_tag() {
$attr_string = generate_attr_string($attr);
return "<" . $tag . " " . $attr_string . ">";
}
?>
Starting to see how content_tag()
is going to work? Stay tuned - we're almost there!
The Final Function
At this point we're really just stringing together our utility methods, using our parameter signature from before. Let's see how it looks!
<?php
function content_tag($tagName, $content, $attr=array()) {
return open_tag($tagName, $attr) . $content . close_tag($tagName);
}
?>
It's almost a disappointing finish - all the fun was in the helper methods! You could put keep all of the code in the content_tag()
method if you wanted to, but I generally try to keep everything separated out into functions. Your choice. Anyways, I hope that you find this function useful one day - the use case I described in the beginning of this post was trivial, but I find this comes in handy when looping through results returned by MySQL or similar.
Anyways, that's hopefully the last I'll speak of PHP for a while. I promise the next code post will be delicious Rails :)
Tweet