Search code examples
phpautoloadrequire-once

PHP global, nested/inherited autoload


PHP 5.3.3-pl1-gentoo (cli) (built: Aug 17 2010 18:37:41)

Hi all, I use a simple autoloader in my project's main file (index.php):

require_once("./config.php");
require_once("./app.php");
require_once("./../shared/SqlTool.php");

function __autoload($className) {
    $fn = 'file-not-exists-for-{$className}';
    if (file_exists("./specific/php/{$className}.php")) { $fn = "./specific/php/{$className}.php"; } else
     { $fn = "./../shared/{$className}.php";}
    require_once($fn);
}

$sql = new SqlHD(); // class SqlHD, in ./specific/php/SqlHD.php extends SqlTool
$web = new HTMLForm($sql); // class HTMLForm in HTMLForm.php
$app = new App($sql, $web); // class App in App.php
$app->Main();

The problem: without that require_once("./../shared/SqlTool.php");, script can't execute SqlHD.php, because it can't find SqlTool.php by itself, and for some reason it doesn't uses autoload routine defined in main file.

I tried this:

spl_autoload_register(__NAMESPACE__ .'\Test::load');

class Test {
    static public function load($className){
        $fn = 'file-not-exists-for-{$className}';
        if (file_exists("./specific/php/{$className}.php")) { $fn = "./specific/php/{$className}.php"; } else
         { $fn = "./../shared/{$className}.php}";}
        echo realpath($fn);//"$curRealDir Filename $fn\n";
        echo "\n";
        require_once($fn);
    }   
}

Well,

PHP Warning: require_once(./../shared/SqlTool.php}): failed to open stream: No such file or directory in /home/beep/work/php/hauthd/index.php on line 20 PHP Fatal error: require_once(): Failed opening required './../shared/SqlTool.php}' (include_path='.:/usr/share/php5:/usr/share/php') in /home/beep/work/php/hauthd/index.php on line 20

So it doesn't reacts to any request from extended class.

Last second idea: put spl_autoload_register to each file. But cannot put it to "extends" directive itself!

P.S. May rewrite SqlTool.php using Factory pattern so it would automatically return an instance of project-specifc class, but it seems to be not a best way, or it is..?


Solution

  • If SqlHD extends SqlTool, then your __autoload() function should include this automatically.

    Note you have an extra '}' in your filename which is probably messing this up. (Which you have also copy 'n' pasted into your 2nd code snippet.)

    { $fn = "./../shared/{$className}.php}";}
    

    As an aside, I think you only need to require() inside your __autoload() function, rather than require_once(), since your __autoload() function is only called if it has not already been loaded.