spl 自动加载寄存器错误
spl autoload register error
我正在写一些 类,我想使用 spl_autoloader_register()
函数加载它们。我创建了一个名为 autoloader.php 的文件,并将其保存在我保存项目所需的所有 类 的文件夹中。
因此,为了验证它是否有效,我在测试 php 页面中使用 require_once
加载了它,但不幸的是,控制台日志显示错误输出 PHP Warning: include_once(lib\DataManager.php): failed to open stream: No such file or directory
.
测试文件在所有 类 所在的同一个文件夹中,是不是因为这个原因导致的错误?
这是自动加载器代码
<?php
function autoloader($className){
include_once($className . '.php');
}
spl_autoload_register('autoloader');
?>
这是我尝试从测试页面实例化它的方式
<?php
require_once 'autoloader.php';
require_once 'config.php';
use lib\DataManager as DataManager;
$dataManager = new DataManager($db);
?>
你几乎答对了。问题是因为它没有指向正确的本地文件系统来查找文件。以下自动加载器将使用相关插件模型和库文件夹模型。这将假定您在配置文件中定义了一个变量 $GLOBALS['config']->lib
,它定义了一个可以包含额外系统库的文件系统文件夹。当然,这可以有不同的定义,这取决于应用程序。
<?php
function autoloader($className){
$paths=[getcwd(),$GLOBALS['config']->lib];
foreach($paths as $p){
$filename = str_replace('\','/',$p.'/'.$className.'.php');
if (is_readable($filename)) {
require_once($filename);
return;
}
}
}
spl_autoload_register('autoloader');
?>
这将考虑两种情况,class 是相对于上次请求的脚本,如果没有则尝试使用 classes 的预定义文件夹。找到并加载后,它应该 return,以避免继续尝试加载其他路径。
在阵列上可以定义更多的尝试路径,但出于性能原因尽量不要超过四个路径。此外,路径的顺序是首先查看的优先级。
此脚本应该适用于 PHP 5.4 up。
相对路径不是相对于写入文件的文件进行处理的,而是PHP进程的"current working directory"(通常是你的web进程的文档根目录,但不值得依赖上)。
为了引用当前源文件的位置,PHP提供了两个magic constants:
__FILE__
是您写入的任何源文件的完全限定文件名
__DIR__
是包含该文件的目录
因此,假设您的 类 与自动加载器函数的定义位于同一目录中,您可以这样写:
function autoloader($className){
include_once __DIR__ . DIRECTORY_SEPARATOR . $className . '.php';
}
__DIR__
在编译函数时解析一次,所以每当这个函数是 运行 时,它总是引用 定义这个函数的目录,不管它是从哪里调用的,或者脚本是如何 运行.
(请注意,include
、require
、include_once
和 require_once
是关键字而不是函数,并且不需要将它们括起来。它不会通常添加它们会造成伤害,但在某些情况下会造成混淆,因此最好避免。)
我正在写一些 类,我想使用 spl_autoloader_register()
函数加载它们。我创建了一个名为 autoloader.php 的文件,并将其保存在我保存项目所需的所有 类 的文件夹中。
因此,为了验证它是否有效,我在测试 php 页面中使用 require_once
加载了它,但不幸的是,控制台日志显示错误输出 PHP Warning: include_once(lib\DataManager.php): failed to open stream: No such file or directory
.
测试文件在所有 类 所在的同一个文件夹中,是不是因为这个原因导致的错误?
这是自动加载器代码
<?php
function autoloader($className){
include_once($className . '.php');
}
spl_autoload_register('autoloader');
?>
这是我尝试从测试页面实例化它的方式
<?php
require_once 'autoloader.php';
require_once 'config.php';
use lib\DataManager as DataManager;
$dataManager = new DataManager($db);
?>
你几乎答对了。问题是因为它没有指向正确的本地文件系统来查找文件。以下自动加载器将使用相关插件模型和库文件夹模型。这将假定您在配置文件中定义了一个变量 $GLOBALS['config']->lib
,它定义了一个可以包含额外系统库的文件系统文件夹。当然,这可以有不同的定义,这取决于应用程序。
<?php
function autoloader($className){
$paths=[getcwd(),$GLOBALS['config']->lib];
foreach($paths as $p){
$filename = str_replace('\','/',$p.'/'.$className.'.php');
if (is_readable($filename)) {
require_once($filename);
return;
}
}
}
spl_autoload_register('autoloader');
?>
这将考虑两种情况,class 是相对于上次请求的脚本,如果没有则尝试使用 classes 的预定义文件夹。找到并加载后,它应该 return,以避免继续尝试加载其他路径。
在阵列上可以定义更多的尝试路径,但出于性能原因尽量不要超过四个路径。此外,路径的顺序是首先查看的优先级。
此脚本应该适用于 PHP 5.4 up。
相对路径不是相对于写入文件的文件进行处理的,而是PHP进程的"current working directory"(通常是你的web进程的文档根目录,但不值得依赖上)。
为了引用当前源文件的位置,PHP提供了两个magic constants:
__FILE__
是您写入的任何源文件的完全限定文件名__DIR__
是包含该文件的目录
因此,假设您的 类 与自动加载器函数的定义位于同一目录中,您可以这样写:
function autoloader($className){
include_once __DIR__ . DIRECTORY_SEPARATOR . $className . '.php';
}
__DIR__
在编译函数时解析一次,所以每当这个函数是 运行 时,它总是引用 定义这个函数的目录,不管它是从哪里调用的,或者脚本是如何 运行.
(请注意,include
、require
、include_once
和 require_once
是关键字而不是函数,并且不需要将它们括起来。它不会通常添加它们会造成伤害,但在某些情况下会造成混淆,因此最好避免。)