Using Closures as callbacks within loops

In jQuery (and other Javascript frameworks) it is quite common to use closures (I refer to them as callback functions) to loop over arrays or objects. Even though it's a slow process and is much more efficient to use the built-in for loop, it got me thinking. Why not try and use the new Closure class in PHP 5.3 and see how well it performs within a loop? Suffice to say, I got some really really interesting results. Before I get into the details, here is the test script I wrote (the Benchmark class is merely a class I have written in the past).

<?php $data = range(0, 1000);
$clean = array();
public function loop($array, Closure $closure) {
	if (!empty($array)) {
		foreach ($array as $key => $value) {
			$closure($key, $value);
		}
	}
}
Benchmark::start('loop');
foreach ($data as $key => $value) {
	$clean[$key] = $value;
}
loop($data, function($key, $value) {
	$clean[$key] = $value;
});
Benchmark::stop('loop');
echo Benchmark::display('loop'); ?>

I didn't get too in depth with my test cases and simply used Firefox and page refresh to get my results. I am running PHP 5.3.1 on a Windows 7 XAMPP installation with Apache and no caching. For benchmarking I was using microtime(true) and memory_get_usage().

I began testing with 4 different cases, each of which that changed the size of the $data array. I started with 1000 iterations, then 5000, then 10000 and lastly 100000. I would comment out the foreach/loop sections and run them one at a time (of course), and ran each test about 5 times to gather an average. Here are the results.

foreach:
1000	Time: 0.0010 / Memory: 137128 (Max: 689160)
5000	Time: 0.0052 / Memory: 706488 (Max: 1258528)
10000	Time: 0.0097 / Memory: 1412048 (Max: 1964120)
100000	Time: 0.0545 / Memory: 13849568 (Max: 14401656)
closure:
1000	Time: 0.0027 / Memory: 84984 (Max: 688832)
5000	Time: 0.0144 / Memory: 433672 (Max: 1258192)
10000	Time: 0.0267 / Memory: 866448 (Max: 1963744)
100000	Time: 0.1223 / Memory: 8525216 (Max: 14401256)

The first thing you will notice is the time it took to interpret the page. On average using a closure as a callback within a loop will take 2-3x longer to process. However, the interesting thing is that the memory usage is around 40% smaller (using more allocated memory) while using a closure than doing a foreach, yet the max allocated is nearly identical. I knew what the outcome would be before I even started it -- Javascript closures are the same way. Regardless it was a fun experiment and if anyone knows more about this, please shed some light on this topic for the rest of us!

But in closing I can sadly say, that no, you should not be using a closure for looping, just stick to the old fashion tried and true foreach or for loop.

Getting the page height with jQuery

I was recently adding an overlay (or modal) feature to one of my sites. This overlay feature required a blackout mask (when your webpage gets covered with an opaque black layer) to be shown over the content. Writing the CSS for this was a breeze, and writing the jQuery (or Javascript) for this was even easier. However, I did run into one little snag.

In current browsers I could do a position fixed on the blackout and define width and height at 100%. While in outdated browsers (Internet Explorer), position fixed does not work properly, so I had to resort to Javascript and position absolute. This was easy as I would grab the height of the page and apply it to the blackout CSS. During my testing I noticed that the blackout would only fill the viewport of the page, and the second you started scrolling you would see where the blackout cut off.

After some browsing of the jQuery API I discovered my problem. It seems that the window and document objects return different heights in jQuery. Window returns the height of the viewport (everything within view) while document returns the height of the HTML page (the whole page, including hidden content that requires scrolling). Furthermore, window and document can not use outerHeight() nor innerHeight(), they must simply use height().

$(window).height(); // returns height of browser viewport
$(document).height(); // returns height of HTML document

Here is how I remember which is which: document returns the height of the DOM (document object model) and window returns the height of the viewport (viewing out a window). I know many of you may of already known this, but it slipped past me and was quite a genius implementation of behalf of the jQuery team.

The end of the HtmlHelper

For the past two years, I have gotten pretty close with the HtmlHelper. It has been there for me, making my life easier than before. But that time has come to an end, so sorry HtmlHelper, you are just too much of a burden now a days. The HtmlHelper has been an amazing convenience by automatically building my anchor links, by creating images with the correct path, or linking my CSS from within separate views, and much much more. But why do all this when you can simply write the HTML yourself?

I am not sure why I didn't notice this sooner; I was probably just stoked on developing with CakePHP so I wanted to do everything the CakePHP way. Lately however, I have noticed that the HtmlHelper really isn't needed that much. I can only think of a few cases where it is needed: linking stylesheets/javascript dynamically, building breadcrumbs and creating routes. Everything else is just consuming PHP logic and processing time to render HTML, which you can simply write yourself in the first place and bypass the PHP interpreter.

Linking Routes

The primary use of the helper, but why not just use url() instead? By doing that you don't have to deal with the hassle of nesting your array of attributes, or escaping variables into the method call. You also don't have to worry about Cake being over zealous and escaping all your data. Take these examples, they deliver the same result.

// With the helper
<?php echo $this->Html->link('Anchor Link', array('controller' => 'news', 'action' => 'index'), array('title' => 'Anchor Title')); ?>
// Without the helper
<a href="<?php echo $this->Html->url(array('controller' => 'news', 'action' => 'index')); ?>" title="Anchor Title">Anchor Link</a>
// Or pure HTML if your routes never change
<a href="/news" title="Anchor Title">Anchor Link</a>
Doctypes and meta tags

Another example of using PHP to render HTML, when you can just write HTML. This gets even easier with HTML5.

<?php echo $html->docType('xhtml-trans');
echo $html->meta('keywords', 'miles johnson php mysql design code developement developer web production creation coding functions tutorials methods scripts packages open source cakephp cake bake controller component model behavior view helper'); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<meta name="keywords" content="miles johnson php mysql design code developement developer web production creation coding functions tutorials methods scripts packages open source cakephp cake bake controller component model behavior view helper" />
Images

This one I am still 50/50 on. It helps by determining the base URL, detecting asset timestamps and appending the alt attribute. But this of course can still be written normally as well. I will let you decide.

<?php echo $this->Html->image('logo.png'); ?>
<img src="/img/logo.png" alt="" />
Divs, paragraphs, tables, lists, script blocks

All of these should never be used in the view or layout. Using PHP to render basic HTML tags like this is absurd in my opinion.

So when should the helper be used?

Like I stated above, there are only a few times when the helper should be used. The first is asset linking (stylesheets and javascript). This allows you to include an asset from within any view, which is then output within $scripts_for_layout. Why is this so awesome? Simple, you can have a specific stylesheet for a specific page, without having to include it on all pages.

Secondly is building breadcrumbs. From within your view you can define the "top level" or "trailing" crumb, and within your layout you can define the base crumbs. This allows you to add multiple levels of crumbs within different layers of views. A quick example, which would give you the trail of: Blog -> Archives -> Blog Title.

// In the view
$this->Html->addCrumb('Archive', array('controller' => 'blog', 'action' => 'archive');
$this->Html->addCrumb($blog['Blog']['title'], array('controller' => 'blog', 'action' => 'read', $blog['Blog']['id']);
// In the layout
$this->Html->addCrumb('Blog', array('controller' => 'blog', 'action' => 'index');

Lastly, the primary reason that the HtmlHelper has all these convenience methods, is so that you can use them within other helpers. Since it's impossible to render HTML within PHP without string concatenation, the HtmlHelper gives other helpers the ability to render HTML easily without all the hardship. That is the primary reason of this helper.

Now all of this is a personal opinion of course, but since I didn't realize most of this for a while, I thought some of you might not have either. This is neither belittling the CakePHP dev team as they have done an awesome job so far, so thank you! So take it how you wish and code how you like. Enjoy!