Autoload and lambda functions

View: New views
3 Messages — Rating Filter:   Alert me  

Autoload and lambda functions

by Markus Wolff :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi there,

I've been toying around with the new bootstapping mechanism and autoload
capabilities in ZF 1.8. To add the icing on the cake, I'm also using PHP
5.3's new lambda functions.

This combination does not yet work for me, though.

Here's an example from my Bootstrap class:

$loader = Zend_Loader_Autoloader::getInstance();

$loader->pushAutoloader(function($class) use ($fileList) {
    error_log("Loading $class with fileList: " . count($fileList));
    if (!empty($fileList[$class])) {
        require_once $fileList[$class];
    }
}, 'phpillow');

$loader->pushAutoloader(function($class) {
    error_log("Loading $class");
    include APPLICATION_PATH . '/models/' . $class . '.php';
}, 'Model');

Now, when I try to invoke a class "ModelFooBar" that extends
"phpillowDocument", I would expect those two functions to be called.
Nothing happens, though.

If I simply call spl_autoload_register instead of using
Zend_Loader_Autoload, everything works fine:

spl_autoload_register(function($class) {
    if (strpos($class, 'Model') === 0) {
        error_log("Loading $class");
        include APPLICATION_PATH . '/models/' . $class . '.php';
    }
    error_log('Tried to find class ' . $class);
});

Am I using the Autoload class wrong, or does it simply not work with
lambda functions yet?

CU
 Markus



Re: Autoload and lambda functions

by Mon Zafra :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

It's because of this method [Zend/Loader/Autoloader.php]:


    /**
     * Autoload a class
     * 
     * @param  string $class 
     * @return bool
     */
    public static function autoload($class)
    {
        $self = self::getInstance();

        foreach ($self->getClassAutoloaders($class) as $autoloader) {
            if ($autoloader instanceof Zend_Loader_Autoloader_Interface) {
                if ($autoloader->autoload($class)) {
                    return true;
                }
            } elseif (is_string($autoloader)) {
                if ($autoloader($class)) {
                    return true;
                }
            } elseif (is_array($autoloader)) {
                $object = array_shift($autoloader);
                $method = array_shift($autoloader);
                if (call_user_func(array($object, $method), $class)) {
                    return true;
                }
            }
        }

        return false;
    }
There's no handler for lambdas. The elseif part should be combined to something like

            } else if (is_callable($autoloader)) {
               return call_user_func($autoloader, $class);
            }

or better yet, the callback validation should be done when adding autoloaders since the autoload method is called often. There's no point in testing if it's callable it every single time.

   -- Mon


On Fri, Jul 3, 2009 at 4:11 PM, Markus Wolff <markus@...> wrote:
Hi there,

I've been toying around with the new bootstapping mechanism and autoload
capabilities in ZF 1.8. To add the icing on the cake, I'm also using PHP
5.3's new lambda functions.

This combination does not yet work for me, though.

Here's an example from my Bootstrap class:

$loader = Zend_Loader_Autoloader::getInstance();

$loader->pushAutoloader(function($class) use ($fileList) {
   error_log("Loading $class with fileList: " . count($fileList));
   if (!empty($fileList[$class])) {
       require_once $fileList[$class];
   }
}, 'phpillow');

$loader->pushAutoloader(function($class) {
   error_log("Loading $class");
   include APPLICATION_PATH . '/models/' . $class . '.php';
}, 'Model');

Now, when I try to invoke a class "ModelFooBar" that extends
"phpillowDocument", I would expect those two functions to be called.
Nothing happens, though.

If I simply call spl_autoload_register instead of using
Zend_Loader_Autoload, everything works fine:

spl_autoload_register(function($class) {
   if (strpos($class, 'Model') === 0) {
       error_log("Loading $class");
       include APPLICATION_PATH . '/models/' . $class . '.php';
   }
   error_log('Tried to find class ' . $class);
});

Am I using the Autoload class wrong, or does it simply not work with
lambda functions yet?

CU
 Markus




Re: Autoload and lambda functions

by weierophinney :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-- Mon Zafra <monzee@...> wrote
(on Friday, 03 July 2009, 06:04 PM +0800):
> It's because of this method [Zend/Loader/Autoloader.php]:

<snip: Zend_Loader_Autoloader::autoload() method>

> There's no handler for lambdas. The elseif part should be combined to something
> like
>
>             } else if (is_callable($autoloader)) {
>                return call_user_func($autoloader, $class);
>             }
>
> or better yet, the callback validation should be done when adding autoloaders
> since the autoload method is called often. There's no point in testing if it's
> callable it every single time.

Could you please post an issue in the tracker for this? You're
absolutely right, and it's a good improvement to include for 1.9.0.

Thanks!


> On Fri, Jul 3, 2009 at 4:11 PM, Markus Wolff <markus@...> wrote:
>
>     Hi there,
>
>     I've been toying around with the new bootstapping mechanism and autoload
>     capabilities in ZF 1.8. To add the icing on the cake, I'm also using PHP
>     5.3's new lambda functions.
>
>     This combination does not yet work for me, though.
>
>     Here's an example from my Bootstrap class:
>
>     $loader = Zend_Loader_Autoloader::getInstance();
>
>     $loader->pushAutoloader(function($class) use ($fileList) {
>        error_log("Loading $class with fileList: " . count($fileList));
>        if (!empty($fileList[$class])) {
>            require_once $fileList[$class];
>        }
>     }, 'phpillow');
>
>     $loader->pushAutoloader(function($class) {
>        error_log("Loading $class");
>        include APPLICATION_PATH . '/models/' . $class . '.php';
>     }, 'Model');
>
>     Now, when I try to invoke a class "ModelFooBar" that extends
>     "phpillowDocument", I would expect those two functions to be called.
>     Nothing happens, though.
>
>     If I simply call spl_autoload_register instead of using
>     Zend_Loader_Autoload, everything works fine:
>
>     spl_autoload_register(function($class) {
>        if (strpos($class, 'Model') === 0) {
>            error_log("Loading $class");
>            include APPLICATION_PATH . '/models/' . $class . '.php';
>        }
>        error_log('Tried to find class ' . $class);
>     });
>
>     Am I using the Autoload class wrong, or does it simply not work with
>     lambda functions yet?
>
>     CU
>      Markus
>
>
>
>

--
Matthew Weier O'Phinney
Project Lead            | matthew@...
Zend Framework          | http://framework.zend.com/