3

在尝试使用 spl_autoload、命名空间和动态类名时,我遇到了一个“奇怪”的事情。我使用 PHP 5.3.2,像这样调用自动加载

set_include_path(get_include_path().PATH_SEPARATOR."classes".PATH_SEPARATOR."utils");
spl_autoload_extensions(".class.php");
spl_autoload_register();

现在到核心。建议以下代码:

new \User\Student;
$name="\User\Student";
new $name();

这工作正常,文件 classes/user/student.class.php 成功加载,两种构造都成功。但是,用法有点不同:

$name="\User\Student";
new $name();
new \User\Student;

在“..Class \User\Student 无法加载...”上失败。我建议它应该以某种方式与静态/动态命名空间解析有关。但是,我认为这两者之间应该没有任何区别,除了它们的处理时间(编译与运行时)。

感谢您的任何解释。

4

1 回答 1

4

这里的“问题”其实比 SPL 级别低,也可以用__autoload(). 这在代码中得到了最好的证明:

function __autoload ($class) {
  echo "Loading $class\n";
}

new Test;
// displays "Loading Test"

$var = 'Test';
new $var;
// displays "Loading Test"

// However, when we introduce namespaces...

new \This\Is\A\Test;
// displays "Loading This\Is\A\Test"

$var = '\This\Is\A\Test';
new $var;
// displays "Loading \This\Is\A\Test"

请注意,当引入命名空间时,前导斜杠在静态调用时不会传递给函数,而是在动态调用时传递给函数。

因此,解决方案是做这些相当简单的事情:

  • 从动态类名实例化中删除前导斜杠。
  • 像这样包装默认spl_autoload()函数:
set_include_path(get_include_path().PATH_SEPARATOR."classes".PATH_SEPARATOR."utils");
spl_autoload_extensions(".class.php");
spl_autoload_register(function($class) {
  spl_autoload(ltrim($class, '\\'));
});

当然,如果你这样做,你也可以删除调用spl_autoload_extensions()并将".class.php"字符串传递给第二个参数spl_autoload()

于 2012-08-14T11:17:39.413 回答