Використання Composer в розробці під Бітрікс

13 Липня 2018

наступна стаття
Максим Ліске

Back End Developer

Максим Ліске
Використання Composer в розробці під Бітрікс

Не часто можна зустріти проект на Бітрікс, в якому не використовуються оброблювачі подій. У більшості випадків, розробники просто пишуть їх у файлі 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. Встановити бібліотеку на проект можна різними способами.

  1. Додати в файл composer.json секцію require:

  2. {
        "autoload": {
            "psr-4": {
                "Avivi\\": "lib/"
            }
        }
       "require": {
            "fzaninotto/faker": "1.7.*"
        }
    }
    

    Якщо надалі буде потрібно встановити ще якісь бібліотеки, то їх потрібно буде просто дописати в цю секцію в форматі: “<ім'я розробника>/<ім'я бібліотеки>”: “версія”.

    Зберігаємо файл і вводимо в консолі: php composer.phar install. Бібліотека разом з усіма залежностями буде встановлена в теку vendor.

  3. Написати в консолі php composer.phar require fzaninotto/faker 1.7.*

  4. В цьому випадку 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. Корисні посилання:

  1. Офіційна документація: https://getcomposer.org/doc.

  2. Дефолтний репозитарій пакетів: https://packagist.org/.

  3. Опис специфікацій PSR: https://www.php-fig.org/psr/.


Схожі статті
Записатись на консультацію

Ми зв'яжемось з Вами протягом 10 хвилин