سوف تكون المقالة طويلة ، لذا استرخ عندما أبدأ.
UPD: كما اتضح ، فإن الطريقة الموضحة في هذه المقالة لا تساعد في جميع الحالات - عندما يتعلق الأمر بـ ORM ، حيث تختلف تسمية الفئات والملفات (على سبيل المثال ، فئة ConfigTable ، الموجودة في ملف config.php) ، تبدأ المشاكل والأخطاء. لذلك ، لا يزال من الأفضل استخدام Composer.
إذن ، Bitrix ، أو بالأحرى ، Bitrix Framework. على الرغم من وجود واجهة برمجة تطبيقات غنية ، هناك حاجة من وقت لآخر لإنشاء فصولك / مكتباتك الخاصة ، بالإضافة إلى ربط تلك التابعة لجهات خارجية. لذلك ، بادئ ذي بدء ، دعنا نلقي نظرة على طرق التحميل التلقائي الحالية.
حسن العمر يشمل / يتطلب. أضفته فقط كمرجع تاريخي. على الرغم من فجر مسار البرمجة الخاص بي ، قمت بوضع الفئات والمكتبات اللازمة في مجلد منفصل ، وأنشأت ملفًا منفصلاً حيث قمت بتضمين كل هذه الفئات ثم أدرجت الملف مع شوائب (أعتذر عن الحشو).
ملحن.يتيح لك ربط كل من الفصول الدراسية ومكتبات الطرف الثالث. ومع ذلك ، عند إضافة فئات جديدة ، فإنه يتطلب تحديثًا يدويًا. بالإضافة إلى ذلك ، يجب أيضًا كتابة الفئات والملفات ومساحات الأسماء يدويًا. يمكنك أن تقرأ عن كيفية تكوين صداقات Bitrix مع الملحن هنا
محمل 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)
لذلك ، يبقى علينا تنفيذ طريقة التحميل التلقائي للصفيف الناتج. لهذا الغرض ، سنكتب أسلوبًا يحمل أكثر الأسماء العادية شيوعًا ، حيث سنمرر المصفوفة الناتجة:
public static function loadClasses(array $classes, $moduleId = null)
{
Loader::registerAutoloadClasses($moduleId, $classes);
}
تستخدم هذه الطريقة محمل بتريكس ، الذي يسجل مصفوفة مع فئاتنا.
الآن لم يتبق سوى القليل جدًا - لتشكيل مصفوفة مع الفئات وتحميلها باستخدام الفصل الدراسي الذي كتبناه. للقيام بذلك ، في مجلد 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;
}
بدلا من الاستنتاج
حسنًا ، تهانينا ، دراجتنا جاهزة وتقوم بعمل ممتاز بوظيفتها.
المصادر ، كما هو الحال دائمًا ، على جيثب .
شكرا على انتباهك.