Converting Brainstorms to Blogs

Saturday, September 22, 2007

A smart __autoload() function for PHP 5 with minimum overhead

Yet another __autoload() function

It took me a while to figure out how I wanted to organize my classes, and how to use __autoload() to load them automatically, instead of having to use require_once() in every script.

My goal was a fast implementation of the __autoload() function, which would not have to do any unnecassary I/O.

I came up with a very small and simple function, which creates the path to the class from the name of the class itself. The only caveat is that classes names and the directory structure must adopt to a very strict naming scheme, which is also case sensitive. But I believe that it doesn't take much time to get used to this scheme, and many people may be using a similar, if not the same, scheme already.

Naming Scheme

  • Base Classes
    • the class name must start with a capital letter
    • the class name can only contain letters
    • the class name can only have one capital letter
    • the class file must resides in a directory with the same name as the class
    • the class file must have the same name as the class followed by the extension .php
  • Extended Classes
    • the extended class name must start with the base class name
    • the extended class name can only contain letters
    • the name after the base class name must start with a capital letter
    • the name after the base class name can only have one capital letter
    • the extended class file must reside in a sub directory of the base class with the same name as the extended class
    • the extended class file must have the same name as the extended class followed by the extension .php

Directory Structure and Class Names

/path/to/classes - BASE_PATH (must be defined in autoload.php script) /path/to/classes/autoload.php - the file containing the __autoload() function /path/to/classes/Shape/Shape.php - class Shape /path/to/classes/Shape/ShapeCircle/ShapeCircle.php - class ShapeCircle extends Shape /path/to/classes/Shape/ShapeRectangle/ShapeRectangle.php - class ShapeRectangle extends Shape /path/to/classes/Shape/ShapeRectangle/ShapeRectangleSquare/ShapeRectangleSquare.php - class ShapeRectangleSquare extends ShapeRectangle

One nice feature of this naming scheme is that your directory tree will look exactly like your classes, your base directories would have your base classes, and each sub directory would have an extended class of it's parent. Classes can be extended multiple times.

To setup this scheme, first the BASE_PATH directory has to be created, and the path has to be defined in the autoload.php script. The __autoload() function should reside in a file by itself in that directory, like in the example above.

Examples

Assuming the previous classes and directory structure, a Shape class could be used like this:

<?php
require_once("/path/to/classes/autoload.php");
$shape = new Shape();
?>

A ShapeCircle class could be used like this:

<?php
require_once("/path/to/classes/autoload.php");
$shape = new ShapeCircle();
?>

Several classes can be used as well, like so:

<?php
require_once("/path/to/classes/autoload.php");
$shape = new Shape();
$circle = new ShapeCircle();
$square = new ShapeRectangleSquare();
?>

The __autoload() Function

And finally, here is the simple but powerful __autoload() function:

<?php // Function to autoload classes // // This function tries to automatically locate a class and do a require_once() // on it if it is found. // // @author DrTebi[at]yahoo[dot]com // @version 0.1 // @date 2007-09-22 // // @public // @param class_name @c string the name of the class, automatically provided by PHP // @return @a void calls require_once() if the class file is found, // triggers an E_USER_WARNING otherwise
define
("BASE_PATH""/path/to/classes");

function 
__autoload($class_name) {
  
$class_base "";
  for (
$i 1$i strlen($class_name); $i++) {
    if (
ord($class_name[$i]) < 97) {
      
$class_base .= substr($class_name0$i) . DIRECTORY_SEPARATOR;
    }
  }
  
$path BASE_PATH DIRECTORY_SEPARATOR $class_base $class_name DIRECTORY_SEPARATOR $class_name ".php";
  if (
is_readable($path)) {
    require_once(
$path);
  } else {
    
trigger_error("Could not load class: " $pathE_USER_WARNING);
  }
}
?>

No comments:

Post a Comment

Blog Archive