Використання Composer в розробці під Бітрікс
13 Липня 2018
наступна статтяНе часто можна зустріти проект на Бітрікс, в якому не використовуються оброблювачі подій. У більшості випадків, розробники просто пишуть їх у файлі init.php, іноді створюють файл handlers.php в тій же теці і під’єднують його через include в ініт. Якщо проект невеликий, наприклад, інформаційний сайт з описом досягнень компанії, то такий підхід не принесе проблем, але на складних або старих проектах ми можемо спостерігати файл з «простирадлом» в кілька тисяч рядків коду, спроби розібратися в якому можуть стати головним болем. Також це стосується власних функцій і класів, які можуть бути розкидані по всьому проекту.
Розглянемо менш поширену, але важливу ситуацію: до проекту необхідно під’єднати сторонню бібліотеку. Все відбувається наступним чином: завантажується архів з бібліотекою, розпаковується в якусь теку сайту і підключається через include в тому місці, де потрібен цей функціонал. А якщо виникає необхідність оновити бібліотеку? Перенести на інший проект? Що якщо бібліотеці для роботи необхідна інша бібліотека, якої у нас немає?
Впоратись з цими проблемами нам допоможе менеджер залежностей — Composer. Основним завданням якого є встановлення необхідних нам версій бібліотек і їх залежностей (які потрібні для роботи потрібних нам бібліотек), а також надає автопідвантаження класів як встановлених бібліотек, так і власного коду. У цій статті розглянемо базові способи використання менеджера залежностей, які допоможуть структурувати проект і полегшать його подальшу підтримку.
Для початку встановимо Composer на проект. Зробити це дуже просто — переходимо на офіційний сайт, викачуємо файл composer.phar і копіюємо його в теку / local /. Все, Composer встановлений. Далі необхідно вказати залежності, які використовуються на проекті. Робиться це через файл composer.json. Для того щоб використовувати тільки автопідвантаження класів, досить прописати в ньому наступне:
{ "autoload": { "psr-4": { "Lib\\": "lib/" } } }
Розберемо летально, що це означає:
-
autoload — позначає секцію, де ми описуємо автопідвантаження класів;
-
psr-4 — вказуємо спосіб підключення класів, в даному випадку це специфікація автопідвантаження класів із шляхів файлів. Більше прочитати про цей стандарт можна тут;
-
"Avivi\\": "lib/" — базовий простір імен і шлях до теки, в якій описані класи. Назву для простору імен можна вказати будь-яку, два зворотних слеша після назви обов'язкові.
Після цього зберігаємо файл composer.json поруч з файлом composer.phar, приєднуємось до сервера по ssh, переходимо в теку/ local / та вводимо команду:
php composer.phar install
Composer сам завантажить все, що йому потрібно. Далі підключаємо на самому початку init.php файл /local/vendor/autoload.php.
require $_SERVER["DOCUMENT_ROOT"] . "/local/vendor/autoload.php";
Для прикладу напишемо простий обробник події OnBeforeIBlockElementUpdate. У init.php пишемо:
<img width=
"512"
src=
"https://lh4.googleusercontent.com/1XhB2INI62X5-HOW3l9rNRR8sfrbvmTX58QCQ-5-rmae4-s4fkQG9qhTHoc9l5gYxyOQ1tnVX6kc2qGAG4OcsjUWogTIDklKlmvcUUcq4pKzxkh0YWg34hnJGueNpJOfUvIXdTyS"
height=
"208"
>
Зверніть увагу на рядок
"Avivi\Handlers\Iblock\IblockElementHandlers",
Таким чином ми вказуємо завантажувачу, де шукати потрібний нам клас. Фактичний шлях до файлу виглядає так: <document root>/local/lib/Handlers/Iblock/IblockElementHandlers.php.
Вміст файлу IblockElementHandlers.php:
namespace Avivi\Handlers\Iblock; class IblockElementHandlers { function OnBeforeIBlockElementUpdateHandler(&$arFields) { file_put_contents( $_SERVER['DOCUMENT_ROOT'].'/log/update_log.txt', date("d.m.Y H:i:s") . " -> " . $arFields['ID'] . "\n", FILE_APPEND ); } }
Тут варто зупинитися докладніше на рядку з оголошення простору імен: namespace Avivi\Handlers\Iblock;
Подібний рядок має бути присутній в кожному файлі з класами. На першому місці базовий простір імен, який ми вказували в файлі composer.json. Далі підпростори, які збігаються з назвами тек, в яких лежить файл з класом. Ім'я класу має бути таким же, як назва файлу, в якому він знаходиться, з дотриманням регістру.
Думаю, на даному етапі вже видно основну ідею такого підходу: класи розсортовані по теках залежно від того, що клас робить і до якого модулю відноситься. З оголошення обробника в init.php можна легко зрозуміти де знаходиться цей клас. Підтримувати структурований таким чином код набагато простіше, ніж один файл в якому описані всі обробники.
Наведемо ще один простий приклад, не пов'язаний з обробкою подій. Створимо в теці/ local / lib / теку Request, а в ній файл CurrencyRate.php:
namespace Avivi\Request; class CurrencyRate { public static function usdToUah() { $url = "http://free.currencyconverterapi.com/api/v5/convert?q=USD_UAH&compact=y"; $ch = curl_init(); curl_setopt ($ch, CURLOPT_URL, $url); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } }
Тепер на будь-якій сторінці в будь-якому місці сайту можемо вивести курс гривні щодо долара:
$currencyRate = Avivi\Request\CurrencyRate::usdToUah()
Тепер розгляньмо підключення сторонніх бібліотек до проекту. Для прикладу встановимо бібліотеку fzaninotto/faker. Встановити бібліотеку на проект можна різними способами.
-
Додати в файл composer.json секцію require:
-
Написати в консолі php composer.phar require fzaninotto/faker 1.7.*
{ "autoload": { "psr-4": { "Avivi\\": "lib/" } } "require": { "fzaninotto/faker": "1.7.*" } }
Якщо надалі буде потрібно встановити ще якісь бібліотеки, то їх потрібно буде просто дописати в цю секцію в форматі: “<ім'я розробника>/<ім'я бібліотеки>”: “версія”.
Зберігаємо файл і вводимо в консолі: php composer.phar install. Бібліотека разом з усіма залежностями буде встановлена в теку vendor.
В цьому випадку Composer сам додасть запис в composer.json. Тепер ми можемо використовувати цю бібліотеку в будь-якому місці проекту:
$faker = Faker\Factory::create(); echo $faker->name;
Також тепер у нас в теці/ local / з'явився файл composer.lock. У ньому зберігається інформація про встановлені бібліотеки і їх версії. Як ви могли помітити, в composer.json для бібліотеки faker версія вказана "1.7. *". Це означає що буде встановлена версія >= 1.7.0, але <1.8.0. Якщо на момент перенесення змін на «бойовий» сайт вийде нова версія, яка відповідає цій умові, то встановиться саме вона, що може призвести до помилок. Для цього і потрібен файл composer.lock в якому вказана точна версія, яка була встановлена. Також цей файл потрібен новим розробникам на проекті, щоб мати можливість встановити в своєму тестовому середовищі потрібні версії бібліотек. Якщо на проекті використовується гіт, то в репозитарій варто додавати тільки файл composer.lock, а файл composer.json додати в .gitignore.
Сподіваюся, я зумів продемонструвати що Composer є прекрасним інструментом для структурування коду і дотримання таких принципів програмування як DRY (Do not Repeat Yourself) і KISS (Keep It Simple Stupid). Пишіть зрозумілий і підтримуваний код;)
P.S. Корисні посилання:
-
Офіційна документація: https://getcomposer.org/doc.
-
Дефолтний репозитарій пакетів: https://packagist.org/.
-
Опис специфікацій PSR: https://www.php-fig.org/psr/.
Ми зв'яжемось з Вами протягом 10 хвилин