Saturday, February 20, 2010

Why you should use an autoload function in PHP

The loading of classes is something that managed languages like Java and C# don't need to worry about, class loaders are built into the compiler. But C/C++ programmers have always had to deal with the issue of accidentally including the same file into a build. They found an easy way around that by wrapping some includes in an
#ifndef CONSTANT
#include 'myfile.h'
#endif
and placing
#ifndef CONSTANT
#define CONSTANT
#endif
into 'myfile.h'. This is a good system for a compiled language that only needs to evaluate these expressions once at build time.

PHP doesn't use this method becuase it has the handy little include functions, include_once and require_once, that prevent you from loading the same file more than once, but unlike a compiled language, PHP re-evaluates these expressions over and over during the evaluation period each time a file containing one or more of these expressions is loaded into the runtime. That is where the Standard PHP Library (SPL), introduced in PHP 5, and the wonderful little _autoload function come in to enhance the speed and uniformity of your PHP code.

__autoload is a magic function, that you define, that enables PHP to let you know when it doesn't have a class loaded, but that class needs to be loaded.

If you define the __autoload function like so,
function __autoload ($classname)
{
    require('/path/to/my/classes/'.$classname.'.php');
}
you no longer need to add
require_once('/path/to/my/classes/MyClass.php');
into your files, because the first time that PHP encounters
$mine = new MyClass();
or
MyClass::staticMethodCall();
it will automatically call the __autoload function that you defined earlier.
__autoload('MyClass');
PHP doesn't do this EVERY time it encounters these calls, just the first time. Thus, you no longer need to add the require_once('/path/to/my/classes/MyClass.php'); to any files at all.

Why is __autoload a good thing?

The primary reason is that it improves the performance of your scripts by preventing PHP from checking if the file has already been loaded or not, like it does every time you call require_once or include_once. Moreover, you no longer have to load a class file just because you MIGHT need it during the execution of you script, because PHP will let you know if it is needed, when it is needed.

Of course, if you are sure that a class is not yet loaded, and that you will positively need that class during the execution of your script, you should by all means use the require() function to include your file. But from personal experience this is something that rarely happens among files that contain classes. For instance if you have a class that extends another class, you know for sure that the other class will be needed, but do you know for sure that it has not already been loaded? Usually not, because typically, you would be extending that parent class with at least one other child class. But I guess this is not always the case, so you should do what you think is best.

Advanced Usage

__autoload also makes it possible to change the include directory for a class based on some identifier in the class name
function __autoload ($classname)
{
    if (strstr('MyNamespace', $classname))
    {
         require('/some/other/path/to/my/classes/'.$classname.'.php');
    }
    else
    {
         require('/path/to/my/classes/'.$classname.'.php');
    }
}
or translate a class name into a file path location

function __autoload ($classname)
{
    //you could also replace '\\', if you are using namespacing in PHP 5.3 or greater
    require('/path/to/my/classes/'.str_replace('_', '/', $classname).'.php');
}
 There are even more techniques that can be used like changing file extensions and so on.

What if I need more than one __autoload function in my script?

One of the greatest things about SPL is that it provides a way to define more than one __autoload function using spl_autoload_register. If you already have an __autoload function you will need to register that function before registering any additional functions though.
spl_autoload_register('__autoload');
spl_autoload_register('my_other__autoload');
Of course if you do this, you will need to use the include function in you autoloaders instead of the require function, or check if a file exists in the expected path, otherwise the next function will never get called, because the runtime will encounter a fatal error. Additionally, spl_autoload_register accepts any 'callable' type variable, meaning that you can use a method from a class as an autoload function as well.
//for a static method
spl_autoload_register(array('MyAlreadyLoadedClass', 'autoloader'));
or
//and for an instatiated object method
spl_autoload_register(array($object, 'someAutoLoader'));

So, what if I just need a simple autoloader?

There is an awesome feature in SPL that allows you to tell PHP where to look for class files by default. Every time the PHP runtime encounters a class that is not yet loaded, it calls the spl_autoload function which in turn looks for files with the same name as the class that is supposed to be loaded in the include_path. It uses the file path extensions that are defined by the spl_autoload_extensions function, having .inc and .php set by default.

So, how do I use this to create a simple loader? If your classes are in files with the same name as the class name, and they are all in the same folder, simply add that folder to the include_path
set_include_path(get_include_path() . PATH_SEPARATOR . '/path/to/my/classes/');
Now every time PHP encounters a class that is not yet loaded, it calls spl_autoload, which looks through the files in each of the include_path folders for a file named MyClass.inc or MyClass.php. This method is slightly faster than the __autoload function, because it is native to the PHP runtime. And if you need to add a file path extension that you want spl_autoload to look for just call
spl_autoload_extensions(spl_autoload_extensions() . ',.class.php');
And spl_autoload will look for files that also end with .class.php.

SPL is chock full of goodies, but the autoload functionality is in my opinion one of the most useful additions that make SPL so useful. You are likely to find great performance increases by using these methods.

Sam Shull: PHP Programming Innovation Award of 2009

The PHP community at phpclasses.org has honored me with the PHP Programming Innovation Award of 2009. I am humbled that the international PHP community has shown such great appreciation for my endeavors and community contributions. I think that the hard work of Manuel Lemos at phpclasses has a very positive effect on the PHP community in providing a centralized place to share experiences and knowledge. If you haven't visited the site recently, I think that you will be pleasantly surprised by the robust diversity and ingenuity of many of the contributors.

Wednesday, February 17, 2010

Cross Browser ECMAScript for XML (E4X)

I have written a cross browser compatible implementation of E4X.

Well, when I say cross browser, I mean that it is capable of handling the methodical implementation of the specification, not the syntactical parts. Many of the key features that make E4X so useful are hard, if not impossible, to reproduce in other javascript engines. But what can be reproduced is the simplicity and namespace handling features that make it possible to create a more fluid handling of XML documents than the DOM specification provides. Additionally all the functionality has been tested in Internet Explorer, so now it's possible to handle namespaces in the browser that makes it so terribly difficult to accomplish.

http://code.google.com/p/xbe4x/

Thursday, February 11, 2010

Thoughts on XHP

I am really happy to hear that Facebook has now officially released XHP, an E4X type of implementation for PHP. My initial thoughts are that PHP was built as a templating engine, and so this innovative approach to templating will only help solidify PHP as the best templating engine for the web. But after reading Rasmus' take on the performance hit that you might sustain from using XHP, I'm not so sure.

In fairness I have not yet actually tried this extension out yet (it is an extension, not like HipHop). The amount of data that you would run through the XHP tags would presumably by fairly small amount of data. I am wondering if it is possible to say use the short tags to write something like:

<?=<b style={$style}>{$container}</b>?>

It might go against the whole "simpler to read" idea, but if ease of use is the goal, then I think that it would most certainly accomplish that. On the upside, this would also keep templates cachable, while enabling a fairly simple syntax to provide designers with. All in all, I think that I will just have to test it for myself.

Wednesday, February 10, 2010

Extensions to jQTouch

A few months back I discovered jQTouch by Dave Kaneda, which is a pretty amazing framework for building mobile WebKit based web apps. It's still in beta, but the animations are very robust, and it is easily extended. And so I set out to write a few extensions that would make jQTouch act more like a native iPhone app.

My initial goal was to write an extension that would enable the same type of horizontal scrolling of images that you see in Apple's App Store. But all I could find on the internet was a vertical scrolling div example by Matteo Spinelli (he has since updated the class to include multi-directional scrolling, sort of a drag feature). This appeared to emulate the 'flick-to-scroll' that makes iPhone apps so useful for mobile computing (IMHO), and had the added benefit of allowing the simulation of a fixed position toolbar. I integrated Matteo's scrolling div into an extension of jQTouch so that the functionality would appear seamless, and allow a designer/developer to simply add a few classes to their creation in order to implement the functionality.

But vertical scrolling wasn't what I was looking for, so I started fiddling with Matteo's script to see how it worked, and how I could alter it to enable horizontal scrolling/sliding. So, after figuring out that Matteo was using WebKit's -webkit-transform CSS property and the translate3d function to animate the changes expressed by a touchmove event, I figured, 'Why can't I just change that to use the translateX function instead?' And after hours of tinkering, I finally got that working too after adjusting the acceleration part of the scrolling divs touchend event.

While I was working on this however, I realized that Apple didn't just scroll right and left, they slid. So I created a different version of the same script that implemented a 'snapTo' method to find the next slide frame in the horizontal or vertical scrolling container. I also added a scaling gesture extension in hopes to one day implement a more robust photo gallery like the native iPhone photo gallery.

One day I will find the time to improve these extensions further, but for now you can find the source code and a few examples at the Google code project that I set up for them, I call it jqextensions.