Search code examples
phpzend-frameworkzend-autoloader

php class not found while in (zend-based) include_path


I have a class which is in a subdirectory of my library-folder in a zend-project. So lets say my app is in /Library/WebServer/Foo/, then php's include path is:

<?php echo get_include_path(); ?>

/Library/WebServer/Foo/application/../library:/Library/WebServer/Foo/library:/usr/share/zend-framework/library/

So now I want to create this class, ignore the random logic, and I should be able to reach it by just saying "new MyValidator_Usernameunique()" or something like that:

/Library/WebServer/Foo/library/MyValidator/Usernameunique.php

class MyValidator_Usernameunique extends Zend_Validate_Abstract
{
     const USERNAME_ALREADY_EXISTS = 'usernameAlreadyUsed';
     const DATABASE_FAILED = 'userDatabaseFailure';

     protected $_messageTemplates = array(
         self::USERNAME_ALREADY_EXISTS => "De gebruikersnaam '%value%' is al in gebruik, gebruik een andere."
         self::DATABASE_FAILED => "Er ging iets mis bij het verbinden met de database."
     );

    public function isValid($value)
    {
        $magic = rand(0,3)
        if($magic==0) {
            $this->_error(self::USERNAME_ALREADY_EXISTS);
            return false;
        }
        if($magic==1) {
            $this->_error(self::DATABASE_FAILED);
            return false;
        }
        return true;
    }
}

So I did exactly that:

/Library/WebServer/Foo/library/Form/Register.php

class Form_Register extends Form_FooForm 
{
    public function __construct() 
    {
        parent::__construct();
        $username = $this->createText('username', 'Gebruikersnaam')->setRequired(true);
        $username->addValidator(new MyValidator_Usernameunique());
    }
}

Which gives:-

[Wed Jul 11 14:07:41 2012] [error] [client 127.0.0.1] PHP Fatal error: Class 'MyValidator_Usernameunique' not found in /Library/WebServer/Foo/library/Form/Register.php on line 14, referer: http://foo/

ignore the line number as I simplified the code a bit.

Of course, this comes natural as /Library/WebServer/Foo/library/MyValidator/ is not in my php include_path and I did not 'require' or 'include' or 'require_once' the file. Yet, as I understand, zend framework is supposed to autoload the file by replacing the _ with / and searching the include_path. And this seems to work fine for the register-form, but fails for the validator. Now, why is this? It is almost the same scenario. Moreover, it also fails when I try to create a MyValidator_Usernameunique directly in a controller-class with the same error-message.

Any thought or indication on why this happens is well appreciated. Moreover, please note, I I am not trying to fix this error, I am trying to better understand autoloading in zend. So please do not propose solutions which make the use of my validator redundant.


Solution

  • Looking at your code, and i might missed it, but it's not really the "standard" zend layout

    i kind of expect to following in the path of your webapp (/Library/WebServer/Foo/)

    • application
      • configs
      • controllers
      • etc
    • library
    • public

    Now you want to add the validator to your library i would do it like

    library

    • MyApp
      • Validate
        • Validator.php

    Inside Validator.php

    class MyApp_Validate_Validator extends Zend_Validate_Abstract
    {
        //Do stuff here
    }
    

    Now that we have this extra part in the library we need to tell zend that we have a extra namespace with our own code in it

    so in application.ini you configure it like this

    autoloaderNamespaces.0 = MyApp_
    

    Now the application (zend) should know where to look for your validator

    so you can now do the following

    create a form (best to place it in application/forms/ but it's up to you ofcourse)

    class Form_Register extends Zend_Form {
    
        public function __construct() {
            parent::__construct();
    
            $username = $this->createText('username', 'Gebruikersnaam')
            ->setRequired(true)
            ->addValidator(new MyApp_Validate_Validator());
    
        }
    }