这篇文章会很长,所以在我开始时请坐下。
UPD:事实证明,本文中描述的方法在所有情况下均无济于事-当涉及到ORM时,类和文件的命名是不同的(例如config.php文件中的ConfigTable类),问题和错误开始出现。因此,最好还是使用Composer。
因此,Bitrix或更确切地说是Bitrix Framework。尽管存在丰富的API,但仍需要不时创建自己的类/库以及连接第三方类/库。因此,首先,让我们看一下现有的自动加载方法。
好旧的包括/要求。我添加它纯粹是为了历史参考。尽管在我编程的初期,我将必要的类和库放在一个单独的文件夹中,创建了一个单独的文件,其中包含了所有这些类,然后才将该文件包含在内(对于重言式,我深表歉意)。
作曲家。允许您连接自己的类和第三方库。但是,添加新类时,需要手动更新。此外,类本身,文件和名称空间也需要手动编写。您可以在
Bitrix loader中阅读有关如何与作曲家结识Bitrix的知识。它用于连接模块和自动加载类。但是,在连接必要的类之前,您将必须形成一个数组,其中的键将是类的名称以及它们的路径值。一切看起来像这样:
$classes = [
'Namespace\\Package\\ClassName' => '/path/to/class.php'
];
Loader::registerAutloadClasses(null, $classes);
定制模块。他们说这是最推荐的方法-创建一个模块,将其安装在管理区域中,然后将其连接到任何地方,然后随便使用。看起来很简单,但实际上我们有以下几点:
- 除了编写类,您还需要注册安装和卸下模块的过程。有许多必需的参数和方法,没有这些参数和方法,模块可能无法正常工作(尽管我不知道,但我尚未对其进行测试)
- 如果不连接模块,类将无法工作
- 将类移到单独的模块中并不总是很有意义
但是,如果您编写了本地模块,然后决定向其添加更多的类,那么使用它们就不再需要重新安装模块了-只需在正确的位置调用必要的方法即可!
好吧,事实上,自行车本身...
在分析完所有上述方法之后,我考虑了要提出的内容,这样就可以简单地将新类添加到特定位置,然后将它们自动加载,而无需在名称空间和文件路径数组中添加新元素。
结果,决定编写一个特殊的模块 -听起来可能很奇怪,但是在我看来,这个想法比向init.php中添加几个功能更成功-该模块将自动从所需目录中加载所有类。
我将省略编写模块安装/删除的过程-无论需要什么,他们都会在源代码中查找并直接使用主要功能。
因为 最初,文件夹嵌套级别的数量是未知的,然后这些方法需要递归。我们还将使用Bitrix \ Main \ Loader类,它将加载这些类。
假设我们决定将所有类都放在/ local / php_interface / lib目录中:
此外,我们可能具有不包含类的文件,因此不应将它们包含在自动加载器中,因此也应考虑这一点。
所以走吧
namespace Ramapriya\LoadManager;
use Bitrix\Main\Loader;
class Autoload
{
}
首先,我们需要获取文件夹的所有内容。为此,让我们编写scanDirectory方法:
public static function scanDirectory(string $dir) : array
{
$result = [];
$scanner = scandir($dir); //
foreach ($scanner as $scan) {
switch ($scan) {
//
case '.':
case '..':
break;
default:
//
$item = $dir . '/' . $scan;
$SplFileInfo = new \SplFileInfo($item);
if($SplFileInfo->isFile()) {
// ,
$result[] = $scan;
} elseif ($SplFileInfo->isDir()) {
// ,
$result[$scan] = self::scanDirectory($item, $result[$scan]);
}
}
}
return $result;
}
输出应为以下内容:
如我们所见,文件结构受到尊重,因此您可以开始形成用于自动加载的数组:
/* $defaultNamespace, .
php-,
*/
public static function prepareAutoloadClassesArray(string $directory, string $defaultNamespace, array $excludeFiles) : array
{
$result = [];
//
$scanner = self::scanDirectory($directory);
foreach ($scanner as $key => $value) {
$sep = '\\';
switch(gettype($key)) {
case 'string':
// ,
$SplFileInfo = new \SplFileInfo($directory . '/' . $key);
$classNamespace = $defaultNamespace . $sep . $key;
if($SplFileInfo->isDir()) {
// , , , ,
$tempResult = self::prepareAutoloadClassesArray($directory . '/' . $key, $classNamespace, $excludeFiles);
foreach($tempResult as $class => $file) {
//
$result[$class] = $file;
}
}
break;
case 'integer':
// - ,
$SplFileInfo = new \SplFileInfo($directory . '/' . $value);
// ( , )
$classNamespace = $defaultNamespace . $sep . str_ireplace('.php', '', $SplFileInfo->getBasename());
// php-
if(
$SplFileInfo->isFile() &&
$SplFileInfo->getExtension() === 'php'
) {
// ,
foreach($excludeFiles as $excludeFile) {
if($SplFileInfo->getBasename() !== $excludeFile) {
//
$result[$classNamespace] = str_ireplace($_SERVER['DOCUMENT_ROOT'], '', $directory . '/' . $value);
}
}
}
break;
}
}
return $result;
}
如果一切都正确完成,那么最后,我们将获得一个生成的数组,以便使用bitrix加载器自动加载:
要检查功能,请将MainException.php文件添加到文件夹中,但包含以下类的异常除外:
<?php
namespace Ramapriya\Exceptions;
class MainException extends \Exception
{
public function __construct($message = null, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
如我们所见,我们的文件已加载到一个类数组中:
展望未来,让我们尝试调用我们的新异常:
throw new Ramapriya\Exceptions\MainException('test exception');
结果,我们将看到:
[Ramapriya\Exceptions\MainException]
test exception (0)
因此,仍然需要为结果数组实现自动加载方法。为此,我们将编写一个具有最普通名称loadClasses的方法,并在其中传递结果数组:
public static function loadClasses(array $classes, $moduleId = null)
{
Loader::registerAutoloadClasses($moduleId, $classes);
}
此方法使用bitrix加载程序,该加载程序在我们的类中注册一个数组。
现在剩下的几乎没有-用类形成一个数组并使用我们编写的类加载它们。为此,请在我们的lib文件夹中创建一个include.php文件:
<?php
use Bitrix\Main\Loader;
use Bitrix\Main\Application;
use Ramapriya\LoadManager\Autoload;
// - ,
Loader::includeModule('ramapriya.loadmanager');
$defaultNamespace = 'Ramapriya';
$excludeFiles = ['include.php'];
$libDir = Application::getDocumentRoot() . '/local/php_interface/lib';
$autoloadClasses = Autoload::prepareAutoloadClassesArray($libDir, $defaultNamespace, $excludeFiles);
Autoload::loadClasses($autoloadClasses);
接下来,让我们将此文件包含在init.php中:
// init.php
$includeFile = $_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/lib/include.php';
if(file_exists($includeFile)) {
require_once $includeFile;
}
而不是结论
好了,恭喜,我们的自行车已经准备就绪,并且在功能方面做得很好。
像往常一样,源在github上。
感谢您的关注。