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 :)

Tags: htmlphp