Як відомо при розробці на Bitrix Framework програміст повинен сам піклуватися про підключення необхідних модулів за допомогою методу CModule :: IncludeModule. Причому підключати модулі необхідно скрізь, де відбувається звернення до api цих модулів. У кожному компоненті, шаблоні, скрипті, функції, методі.
А в чому, власне, проблема?
У невеликих проектах, можливо, це не становить ніякої складності, але у відносно великих проектах може набити оскому навіть самому невибаглива програмісту.
Ось простий, наочний приклад, хоч і не дуже життєвий:
Тут ми бачимо дві функції, які через api Інфоблоки отримують списки розділів. Нам заздалегідь невідомо в якому порядку будуть викликатися ці функції і чи будуть взагалі викликатися на даному хіті. Тому доводиться використовувати CModule :: IncludeModule в кожній з них. Це призводить до захаращення коду непотрібними конструкціями, погіршує його читабельність. Та й постійно доводиться стежити, щоб всі модулі були підключені. Все це створює, хоч і невеликі, але все ж незручності при розробці, ускладнює супровід коду. Особливо актуально для великих проектів.
легко забути
CModule :: IncludeModule ще неприємний тим, що про необхідність його використання легко забути. Справа в тому, що він не завжди потрібен для нормального функціонування вашого коду і ваш код до пори до часу буде працювати і без нього.
Таке можливо, наприклад, коли перед кодом, виконується компонент, який і підключає необхідний модуль. В цьому випадку код буде прекрасно працювати незалежно від наявності в ньому CModule :: IncludeModule. Але що станеться, якщо адміністратор забажає відключити цей компонент? Правильно, fatal error.
Може бути для когось постійний виклик CModule :: IncludeModule не представляє ніякої складності, але навіщо ж робити вручну те, що можна змусити виконуватися автоматично. Тим більше, що реалізується Автопідключення модулів всього лише кількома рядками коду:
Пишемо цей код, наприклад, в init.php і про ручному підключенні модулів можна забути раз і назавжди.
Проблема позначена, рішення знайдено. Далі буде багато букв про те, як це працює.
Як це працює?
У Бітрікс є свій автозавантажувач класів, який працює на основі карти класів. Ця карта формується при підключенні модулів. При підключенні кожен модуль реєструє свої класи в карті класів Автозавантажувач.
Відповідно, якщо модуль не підключений, то автозавантажувач Бітрікс нічого не знає про його класах і не зможе підключити їх, коли це буде необхідно. У підсумку ми бачимо fatal error, якщо використовуємо клас без підключення модуля.
Суть рішення полягає в тому, щоб зареєструвати в стеці Автозавантажувач ще один обробник. Управління до цього обробника буде доходити тільки в тому випадку якщо модуль не підключений. Оброблювач виконує наступні функції:
- Визначення до якого модулю відноситься необхідний клас
- Підключення цього модуля
- Передача управління Автозавантажувач Бітрікс
Чий це клас?
Автозавантажувач модулів повинен визначити до якого модулю відноситься клас. В наведеному вище прикладі для цього використовується карта класів, в якій прописано відповідність класів модулів. Це найпростіше рішення. Карта статична, вона зашита в коді. Її потрібно підтримувати в актуальному стані, вручну дописувати нові класи, що не дуже зручно.
Насправді ця карта класів, хоч і дещо в іншому вигляді, все ж таки присутня всередині бітріксового Автозавантажувач. Можливо існує спосіб витягти її, наприклад за допомогою Reflection. У цьому випадку необхідність вручну підтримувати карту класів відпадає.
А як же функції?
А функції в прольоті. У PHP отсутствуем механізм автозавантаження функцій. Тому якщо ви хочете використовувати, наприклад, функцію stemming. то будьте ласкаві попередньо підключити модуль пошуку search.
Тепер пропоную поглянути з висоти пташиного польоту на те, як буде працювати автозавантаження класів з встановленим Автозавантажувач модулів.
Припустимо у нас все ще не підключений модуль Інфоблоки і ми намагаємося виконати наступний код:
- Клас CIBlockElement ще не був оголошений і PHP покладає почесний обов'язок знайти і підключити зниклий клас на перший обробник з стека автозавантаження. Тобто на автозавантажувач Бітрікс.
- Автозавантажувач Бітрікс, безуспішно намагаючись знайти CIBlockElement, втрачає довіру PHP.
- PHP, щоб виправити становище, передає управління наступному оброблювачу, тобто нашому Автозавантажувач модулів.
- Автозавантажувач модулів визначає, що CIBlockElement належить модулю iblock і підключає цей модуль, після чого передає управління Автозавантажувач Бітрікс.
- Автозавантажувач Бітрікс, не вірячи своєму щастю, знаходить клас CIBlockElement в своїй карті класів і, нарешті, підключає його.
- Профіт!
Таким чином, легким рухом руки, ми позбавили себе від ще однієї рутинної роботи і зробили процес розробки на Bitrix трохи приємніше.