How to autoload Table and Row classes in ZF

This article describes how to use a little hack into the Zend Framework library, for having it autoload an ExampleModel.php file whenever an ExampleTable or ExampleRow class is instantiated.

In my Zend Framework projects I use to split my models into a Table and a Row class, and I put both into the same file, one after the other.

For example, my PersonModel.php holds PersonTable and PersonRow classes. I like to have collection methods like findByFullname into the PersonTable class and instance methods like getGroups into the PersonRow class. And it’s very helpful to have these classes into the same file, due to their coupling.

Zend Framework supports autoloading, and it’s possible to replace the default autoloader with your own, but the autoloading replacement feature is compromised by the use of direct calls to the default loader throughout the library (it occurs 50+ times in ZF 1.6.x).

1. Patch Zend_Loader

Patched Zend_Loader differs from Zend_Loader only for the added lines 7-10. The patch is a contribution of Tomáš Procházka who described it in the issue ZF-2533.

    public static function loadClass($class, $dirs = null)
    {
        if (class_exists($class, false) || interface_exists($class, false)) {
            return;
        }

        if (spl_autoload_functions()!==false) {
          spl_autoload_call($class);
          if (class_exists($class, false) || interface_exists($class, false))  return;
        }

        if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
...

2. Add My_Loader

My_Loader differs from Zend_Loader only for the added line 14.

    public static function loadClass($class, $dirs = null)
    {
        if (class_exists($class, false) || interface_exists($class, false)) {
            return;
        }

        if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
            require_once 'Zend/Exception.php';
            throw new Zend_Exception('Directory argument must be a string or an array');
        }

        // autodiscover the path from the class name
        $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
        $file = preg_replace('/^(?!Zend)(.*?)(?:Table|Row).php$/', '$1Model.php', $file);
        if (!empty($dirs)) {
...

3. Register My_Loader as a replacement for Zend_Loader

Finally, at the beginning of my bootstrap file I register My_loader as the real loader.

...
	require_once 'Zend/Loader.php';
	Zend_Loader::registerAutoload( 'My_Loader' );
...

Final thoughts

The issue ZF-2533 is very old, the proposed patch is simple and effective, still it does not find its way into the trunk. Why?

Leave a Reply

Your email address will not be published. Required fields are marked *