我有一个自动加载器,作为一个php文件上面的所有其他子目录在我的项目。
它的作用是为任何特定的服务器请求一次加载所有可能的类。经过进一步的思考,我得出结论,我只需要自动加载所需的类。
我需要做些什么来避免加载其他不需要的类?
如果我需要在我的子目录中发布类文件的相关代码片段,我可以。
<?php
namespace autoloader;
class autoloader
{
private $directoryName;
public function __construct($directoryName)
{
$this->directoryName = $directoryName;
}
public function autoload()
{
foreach (glob("{$this->directoryName}/*.class.php") as $filename)
{
include_once $filename;
}
foreach (glob("{$this->directoryName}/*.php") as $filename)
{
include_once $filename;
}
}
}
# nullify any existing autoloads
spl_autoload_register(null, false);
# instantiate the autoloader object
$classes = [
new autoloader('request'),
new autoloader('config'),
new autoloader('controllers'),
new autoloader('models'),
new autoloader('data')
];
# register the loader functions
foreach ($classes as $class)
spl_autoload_register(array($class, 'autoload'));
所有注册的自动加载器函数将在您尝试实例化新类或直到它最终加载类或抛出错误时被调用。按照现在的方式,您将为每个目录和文件一次又一次地注册相同的自动加载器函数。
你想要做的是沿着这条线。
namespace autoloader;
class autoloader
{
public function __construct()
{
spl_autoload_register([$this, 'autoload']);
}
public function autoload($classname)
{
if (! file_exists("{$classname}.class.php")) {
return;
}
include_once "{$classname}.class.php";
}
}
new autoloader();
每个自动加载器函数都获得传递给它的类FQCN,从那里您必须解析它并确定是否可以加载该类存在的文件。例如,如果我执行以下操作:
use SomeAwesomeClassFile;
$class = new ClassFile();
我们注册的自动加载器将获得作为参数传入的字符串SomeAwesomeClassFile
,然后我们可以解析并查看我们是否有该类的文件,如果没有,我们返回函数并让下一个注册的自动加载器函数尝试找到该类。
你可以在文档中阅读更多关于自动加载器的信息,我也在两个月前写了一篇关于它的博客文章,你可能会感兴趣。
我必须重构代码并删除不必要的load all功能,因为我错误地认为这些功能会根据请求惰性加载我的类。
这是我想到的:
入口点
<?php
require_once 'enums.php';
require_once 'api.class.php';
spl_autoload('AutoLoaderAutoLoader');
use AppAPI;
class MyAPI extends API
{
public function __construct($request){
parent::__construct($request);
}
}
$api = new MyAPI($_REQUEST);
echo $api->processRequest();
自动加载器实现(位于子目录AutoLoader/AutoLoader .php下,通过浏览器使用.htaccess无法访问)
<?php
namespace Autoloader;
spl_autoload_register("AutoLoaderAutoLoader::ClassLoader");
spl_autoload_register("AutoLoaderAutoLoader::RequestLoader");
class Autoloader
{
public static function ClassLoader(String $fileName)
{
foreach ([".Class.php", ".php"] as $extension)
if (file_exists($fileName.$extension))
include $fileName.$extension;
}
public static function RequestLoader()
{
self::ClassLoader('Request');
}
}
processRequest()的代码片段(位于api.class.php - my request router中)
public function processRequest()
{
$id1 = $this->requestObj->id1;
$id2 = $this->requestObj->id2;
$endpoint1 = $this->requestObj->endpoint1;
$endpoint2 = $this->requestObj->endpoint2;
$goto = $this->requestObj->goto;
$isDestination = in_array($id1, ['first', 'prev', 'next', 'last']);
$numSetEndpoints = (int)isset($endpoint1) + (int)isset($endpoint2);
switch($numSetEndpoints)
{
case 0:
if ($isDestination)
return json_decode($this->_response("No Endpoint: ", $endpoint1));
return json_decode($this->_response("No Endpoint: " . $endpoint2 ?? $endpoint));
case 1:
$className = $endpoint1.'Controller';
break;
case 2:
$className = $endpoint2.'Controller';
break;
}
$class = "\Controllers\$className";
if (class_exists($class))
{
$method = strtolower($this->method);
if (method_exists($class, $method))
{
$response = (new $class($this->requestObj))->{$method}();
if ($response['Succeeded'] == false)
{
return $response['Result'];
}
else if ($response['Succeeded'] == true)
{
header("Content-Type: application/json");
return $this->_response($response);
}
else if ($response['Result'])
{
header("Content-Type: text/html");
return $this->_response($response);
}
}
}
}