PHP 全局、嵌套/继承自动加载

发布于 2024-09-26 17:38:42 字数 1874 浏览 14 评论 0原文

PHP 5.3.3-pl1-gentoo (cli)(构建时间:8 月) 2010年17月18:37:41)

大家好,我在项目的主文件(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();

问题:没有 require_once("./../shared/SqlTool.php") ;,脚本无法执行SqlHD.php,因为它本身无法找到SqlTool.php,并且由于某种原因它不使用主文件中定义的自动加载例程。

我试过这个:

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);
    }   
}

嗯,

PHP 警告: require_once(./../shared/SqlTool.php}): 无法打开流:没有这样的文件或 目录在 /home/beep/work/php/hauthd/index.php 第 20 行 PHP 致命错误: require_once(): 打开失败 需要'./../shared/SqlTool.php}' (include_path='.:/usr/share/php5:/usr/share/php') 在 /home/beep/work/php/hauthd/index.php 第 20 行

因此它不会对扩展类的任何请求做出反应。

最后一个想法:将 spl_autoload_register 放入每个文件中。但不能将其放入“扩展”指令本身!

PS 可以使用工厂模式重写 SqlTool.php,以便它会自动返回项目特定类的实例,但这似乎不是最好的方法,或者它是..?

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..?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

︶ ̄淡然 2024-10-03 17:38:42

如果 SqlHD 扩展了 SqlTool,那么您的 __autoload() 函数应该自动包含此函数。

请注意,您的文件名中有一个额外的“}”,这可能会搞砸。 (您也将“n”复制粘贴到第二个代码片段中。)

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

顺便说一句,我认为您只需要在 __autoload() 函数中使用 require() ,而不是 require_once (),因为您的 __autoload() 函数仅在尚未加载时才会被调用。

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.

最偏执的依靠 2024-10-03 17:38:42

[编辑:删除了不正确的相对路径建议 - w3d 发现了真正的问题。将其余部分留在这里仅供参考]

此外,您还可以将自动加载函数中的 require_once 更改为 require - 根据定义,该函数仅在该类尚未加载时才会运行包括。

您可以通过使用包含路径来极大地简化自动加载,因为 PHP 会为您检查不同的位置。例如这样的事情:

set_include_path(
    realpath('./specific/php') . PATH_SEPARATOR .
    realpath('./../shared') . PATH_SEPARATOR .
    get_include_path()
);

function __autoload($className) {
    require "$className.php";
}

[Edit: removed incorrect relative path suggestion - w3d spotted the real problem. Leaving the rest here just for info]

Also you can change the require_once in the autoload function to just require - by definition the function will only run if the class has not already been included.

You could greatly simplify your autoload by utilising the include path, as then PHP would check the different locations for you. E.g. something like this:

set_include_path(
    realpath('./specific/php') . PATH_SEPARATOR .
    realpath('./../shared') . PATH_SEPARATOR .
    get_include_path()
);

function __autoload($className) {
    require "$className.php";
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文