我在脚本中使用__autoload根据需要包含类。我的脚本使用类名中的提示来查找包含它的文件。如果它在模型中结束,它在模型目录中,控制器在控制器目录中等。我开始实现接口,因此需要调整我的自动加载器。
理想情况下,创建对象时,自动装带器将确定对象的文件名,存储位置,并包含该文件。然后,它将询问该类所实现的接口,然后自动包含这些文件。
像
这样的东西function __autoload($classname){
echo $classname;
include ("classes/$classname.php");
$interfaces = class_implements($classname,FALSE);
foreach($interfaces as $name){
if(!class_exists($name,FALSE)){
include("interfaces/".$name."inter.php");
}
}
}
除非我这样做,否则会收到错误
无法重新声明__autoload()(之前在声明中声明) W:\ xampp \ htdocs \ test \ auto.php:5)在W:\ xampp \ htdocs \ test \ auto.php上 第11行
是不是可以在__autoload()中执行此操作?我是否应该继续依赖命名约定来区分对象类型和存储位置?
答案 0 :(得分:7)
在定义实现的接口之前,无法定义类,并且其他任何未知接口也会触发自动加载功能。这意味着在第3行包含类时,它将再次触发自动加载功能 ,接口为$classname
。现在当从第二个__autoload()
返回时 - 它将再次尝试包含接口,由于“已经定义”,它将失败。
其他:不建议使用__autoload()
}使用{{1}}
答案 1 :(得分:4)
使用spl_autoload_register注册其他自动加载功能。您指定的自动加载功能是回调。这意味着您可以传递方法或类方法。这样,您可以将额外的自动加载添加到您的各种类,而不必担心命名冲突。
[编辑]
它不会以这种方式工作。请参阅KingCrunch的智能答案。
即使这样可行,我也会反对。通过使用单个自动加载功能,或者您使用的每个库或框架可能具有其他自动加载功能,您可以保持自动加载简单明了。添加额外的功能可能会使调试变得过于复杂。
答案 2 :(得分:2)
由于您已经依赖于类的命名约定,因此只需修改现有的__autoload来解析接口名称。如果您将所有接口命名为“I_something”,则应该是一个简单的更改。
如果您不想依赖命名约定,那么您需要设置某种类和接口注册表。注册表可以像硬编码数组一样简单,例如:
function __autoload($classname) {
$classlist=array('MyClass1','path/to/file/myclass1.php',
'MyClass2','path/to/file/foo.php',
...
);
$interfacelist=array('MyInterface1','path/to/file/bar1.php',
'I_foo','path/to/file/bibble.php',
...
);
$path=$classname;
if(array_key_exists($classname,$classlist)) {
$path=PATH_CLASSES.$classlist[$classname];
} else if(array_key_exists($classname,$interfacelist)) {
$path=PATH_INTERFACES.$interfacelist[$classname];
}
if(file_exists($path)) {
require_once($path);
} else {
$e=new Exception("Problem with path: $path");
}
}