SiteCrafting Blah Blah Blog

Feb. 2, 2007 at 10:11am

Script Timing, v2

Making the timer look better

Last time, I outlined a way to create a simple PHP script timer. I use this timer in many of the projects that I work on, and it's really helpful to nail down trouble spots in scripts. The thing that it lacks, however, is a decent display. When you call the elapsed() function, it only gives you a number. Creating a decent display for each timer call is tedious and boring. So I simplified it. Now, I'm going to extend the existing Timer class and add some new functionality - make it look better and make it easier to call and display the information.

Take a quick look at the class I developed last time, because I'm going to build on that this time. PHP, just like any Object Oriented language, offers the ability to build on classes using the extends keyword. Basically, this means that the new class is a variant, or child, of the class that's getting extended. The children classes inherit all functions and data not marked as private from the parent classes. This class will look prettier than the previous timer, so I'll call it Pretty_Timer. (Original, huh?)

class Pretty_Timer extends Timer {

}

There's several things that I want to add to this timer, but the first one is a label for the timer. That will help minimize confusion when viewing the output of the timer.

class Pretty_Timer extends Timer {
    var $label;

    function Pretty_Timer($label = "") {
        parent::Timer();

        $this->label = $label;
    }

    function elapsed() {

        $time = parent::elapsed();

        return $this->label.": ".$time;
    }
}

You'll notice that I put the label in the constructor rather than as a separate method. That's to avoid two lines of code to simply set the label. It's optional, so you're not forced into using the label if you don't want to. Also, we have to explicitely call the parent constructor, of the object's time value won't be initialized.

In the elapsed function, I'm getting the elapsed time from the parent Timer, and displaying that and this object's label together. This is pretty useful, but it's still not much to look at. I want add some formatting and CSS to make it look good.

class Pretty_Timer extends Timer {
   
    var $style = 'padding: .25em; margin: .25em; font-family: arial, sans-serif; font-size: 9pt;';
   
    var $green = 'background: #cfc; border-top: 2px solid #0c0; border-bottom: 2px solid #0c0;';
    var $yellow = 'background: #ffc; border-top: 2px solid #fd0; border-bottom: 2px solid #fd0;';
    var $red = 'background: #fcc; border-top: 2px solid #f00; border-bottom: 2px solid #f00;';
   
    var $label;
   
    function Pretty_Timer($label = "") {
        parent::Timer();
       
        $this->label = $label;
    }
   
    function elapsed($formatted = true) {
       
        $time = parent::elapsed();
       
        if($formatted) {
            $out = '<div style="'.$this->style.' ';
           
            if($time < .5) {
                $out .= $this->green;
            }
            elseif($time < 2) {
                $out .= $this->yellow;
            }
            else {
                $out .= $this->red;
            }
           
            $out .= '">'.($this->label != "" ? '<strong>'.$this->label.'</strong> ' : 'Elapsed Time: ').$time.'</div>';
           
            return $out;
        }
        else {
            return $time;
        }
       
    }
}

I've added in some styles, and set it up so that if the elapsed time is greater than half a second, the display will be yellow, as a warning. Your scripts should be running faster than that anyways. If they take more than two seconds, they show up red. People will begin to notice the delay at that point, and you don't want users waiting to use your application. There's also some basic formatting in there, for margins and padding. You should also take note that the elapsed function has a boolean parameter that will remove the formatting if you want it to.

This is all well and good, but there's still something lacking. In the context of an HTML page, you might want to get time information after the page has begun to load. To make that easiser I created a function that has one line of code: echo $this->elapsed(); There isn't a whole lot of difference using this function, display_elapsed(), or the single line of code that it executes, but most IDE's have auto complete, so it's easier and faster to call $timer->display_elapsed();.

So with a little tweaking, we can make the timer faster and easier to use. To show off the functionality, if we have some code that looks like this:

$timer = new Pretty_Timer("My Timer");
$second = new Pretty_Timer("Another Timer");

echo "Just started the timers...";

$timer->display_elapsed();

echo "doing some complex calculations...";
intense_function();

$second->display_elapsed();
$second->reset();
echo "reset the second timer...";
$second->display_elapsed();

echo "A few more calculations that are even more intense...";
complex_calculations();

$timer->display_elapsed();

The output will look like so:

Pretty Timer Demo

And here's the final class:

<?php

class Pretty_Timer extends Timer {
  
    var $style = 'padding: .25em; margin: .25em; font-family: arial, sans-serif; font-size: 9pt;';
  
    var $green = 'background: #cfc; border-top: 2px solid #0c0; border-bottom: 2px solid #0c0;';
    var $yellow = 'background: #ffc; border-top: 2px solid #fd0; border-bottom: 2px solid #fd0;';
    var $red = 'background: #fcc; border-top: 2px solid #f00; border-bottom: 2px solid #f00;';
  
    var $label;
  
    function Pretty_Timer($label = "") {
        parent::Timer();
      
        $this->label = $label;
    }
  
    function elapsed($formatted = true) {
      
        $time = parent::elapsed();
      
        if($formatted) {
            $out = '<div style="'.$this->style.' ';
          
            if($time < .5) {
                $out .= $this->green;
            }
            elseif($time < 2) {
                $out .= $this->yellow;
            }
            else {
                $out .= $this->red;
            }
          
            $out .= '">'.($this->label != "" ? '<strong>'.$this->label.'</strong> ' : 'Elapsed Time: ').$time.'</div>';
          
            return $out;
        }
        else {
            return $time;
        }
      
    }
  
    function display_elapsed() {
        echo $this->elapsed();
    }
  
}

?>

Posted in CSS, PHP, Software Engineering by Dave Poole

Comments (2)

is that a good idea to put div tags into your php code?
1 | Left by somebody | Mar. 26, 2007 at 2:46am


Dave says:

Unfortunately, PHP can't do anything for the way a page, script, or block of data looks. All it really can do is output a string, and any changes to the way the data looks must be done with HTML and CSS. The purpose of this article was to make the timer look better than raw data, and so it was necessary to use some HTML tags to format that data.

So, is it a good idea? Yes, because it was necessary to solve the problem I set before myself. The div tags won't interfere with HTML layouts, but you really shouldn't be displaying this kind of information on a production site anyways. If you want a version of the timer without the tags, you can always take a look at http://sitecrafting.com/blog/making-php-script-timer/ .
2 | Mar. 26, 2007 at 10:17am


Remember me
Name: Email: URL: Comment: *   No HTML, http:// will auto-link
* required    Comment Guidelines