multiple spl_autoload_register issue
-
07-07-2021 - |
Domanda
I'm working on the development of a custom framework. And I have encountered an issue when I tried to dynamise the calling of my classes.
This is a visual of my files :
So I decided to create a different function for each folder (libs, controllers et modeles):
function autoloadLibs($class) {
//require the general classes
require 'libs/' . $class . '.php';
}
function autoloadModels($class) {
//require the models classes
require 'models/' . $class . '.php';
}
function autoloadControllers($class) {
//require the controllers classes
require 'controllers/' . $class . '.php';
}
spl_autoload_register ('autoloadLibs');
spl_autoload_register ('autoloadControllers');
spl_autoload_register ('autoloadModels');
Nevertheless I have this message : Warning: require(libs/admin.php): failed to open stream, of cours it's not the good folder. But I don't know how to fix that. Is there a good way to optimise my classes calls ?
Soluzione
After few tests, I found this solution for my case :
set_include_path(implode(PATH_SEPARATOR, array(get_include_path(), './libs', './controllers', './models')));
spl_autoload_register();
Altri suggerimenti
You need to check the file exists first with is_file()
before you attempt to require
it.
When using spl_autoload_register()
, I've found it's generally better to register one method to include the files. The fact that you can bing multiple functions I believe is to make interoperability with different libraries easy (so they don't clobber __autoload()
). It will also save you having to write the code out multiple times to check for the file's existent, map _
to directory separator (if you do that), etc.
So, assuming you change your filenames to suit the convention of Underscore_Separated_Name
, e.g. Controller_Admin_Dashboard
, you could use...
function autoload($className) {
$path = SYSPATH .
str_replace("_", DIRECTORY_SEPARATOR, strtolower($className)) .
".php";
if (is_file($path)) {
require $path;
}
}
The first time you instantiate Controller_Admin_Dashboard
, PHP may include a file such as /app/controller/admin/dashboard.php
.
If you have multiple spl_autoload_register
calls you need to make sure you don't use the require
keyword to include the files, because this means "include the file or die if it can't".
Personally I disagree with others about only having one autoload function, especially if you are including classes from different locations, such as a controllers versus some library directory. I also check if the file exists first, then include it.
tl;dr version: Don't allow spl_autoload_register
calls to block each other.
your answer is here. when you are registering multiple autoloaders, php try to load a class by anyone of those autoloaders, Then, php calls those autoloaders from the first registered to the last. Then, in anyone of those autoloaders you should check that file_exists or not, else, php try to include it and throws an error if that file does not exist. Then, before inclusion, check existance of file. Change Your Autoloaders To:
function autoloadLibs($class)
{
#require the general classes
$file = 'libs/' . $class . '.php';
if(file_exists($file))
require $file;
}
function autoloadModels($class)
{
#require the models classes
$file = 'models/' . $class . '.php';
if(file_exists($file))
require $file;
}
function autoloadControllers($class)
{
#require the controllers classes
$file = 'controllers/' . $class . '.php';
if(file_exists($file))
require $file;
}
You should check class names before requiring the file, for example:
function autoloadControllers($class) {
//require the controllers classes
if( substr( $class, -10) == 'Controller')){
require 'controllers/' . $class . '.php';
}
}
I find it correct to cause error if class cannot be loaded, but you should make sure that require
is called only on correct path.
Note that spl_autoload_register
provides a third parameter (prepend
). You can set this to true
if you wish to place a specific autoload function on top of the autoload stack. This means that this specific function will then be called first.
Example:
spl_autoload_register(array('My_Class', 'My_Method'), true, true);
http://www.php.net/manual/en/function.spl-autoload-register.php