Примірник Magento 2 Helper


11

Коли я думаю, що я закрутив голову навколо системи DI від Magento 2, щось підходить і розгортає його.
Я бачу в основному коді різні способи доступу до помічника.
Наприклад, Magento\Catalog\Controller\Category::_initCategoryє таке:

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

Але в Magento\Catalog\Block\Category\Viewхелпер вводиться ін конструктор

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

Це спонукає мене думати, що до контролерів слід звертатися по-різному в контролерах і блоках (і моделях), але тоді я знайшов контролер, де в конструктор вводиться помічник Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute.

Будь ласка, очистіть для мене туман.
Коли я повинен використовувати DI і коли я повинен використовувати objectManager? і чому?
Я читав це питання: Миттєві помічники в Magento 2 . Це лише додаткове питання щодо цього.

Відповіді:


10

Я вважаю за краще DI, де це можливо, так як використання диспетчера об'єктів - це вже порушення проти закону про деметер При використанні диспетчера об'єктів ці залежності просто приховані в логіці методу.


Так. Я згоден. Я буду використовувати DI, але мені цікаво, чому це робиться в основі? Можливо, хтось ще не потрапив на рефакторинг класів, про які я згадав?
Маріус

Афаїк, вони все ще багато переробляють і сподіваються, що вони також торкнуться цих місць. Але також не знаю про пріоритети, які повинні існувати, якщо вони хочуть насправді звільнитись у якийсь момент. Тож, можливо, спочатку будуть виправлені деякі нові функції чи інші погані практики.
Тобіас

Що робити, якщо у вас клас 10 функцій, а ТІЛЬКО 1 функція вимагає конкретної моделі? Чи не буде зайвим (з точки зору продуктивності) завантажувати модель за допомогою конструкторської інжекції для кожної з 10 функцій, тоді як ми можемо завантажувати її за допомогою диспетчера об'єктів лише в одній функції
JohnyFree

6

Я не так багато знаю про реалізацію Magento, але схоже, що ObjectManagerце - Локатор послуг .

Як правило, використання Локатора послуг для доступу до залежностей в об'єкті досить погано, ознайомтеся з цією статтею .

Виразно визначити свої залежності через конструктор - це набагато кращий підхід. Це допомагає в тестуванні одиниць і запускає питання щодо часу, коли послуги не визначаються.

Введення диспетчера об'єктів у клас - це в основному введення Реєстру до вашого класу, який має доступ до всіх ваших служб прикладних програм, що, очевидно, не вірно.

Я досить часто використовую ZF2 і, як правило, визначаю невеликі фабричні класи для служб, контролерів та будь-якого класу, які вимагають залежностей. Ці фабричні класи мають доступ до локатора послуг і захоплюють усі сервіси, від яких залежить об'єкт, і вводять їх через конструктор. Використання локатора сервісу у фабричному класі - це добре, оскільки це здебільшого викинути код, наприклад, такий .

Ці заводи ще легко перевірити .

ІМО. Використовуйте інжектор конструктора, коли це можливо. Знову ж таки, я не знаю надто багато про реалізацію Magento, і якщо вона має концепцію Фабрики, з швидкого погляду це виглядає так, як вона їх підтримує, але чітко визначає ваші класи та використовує Локатор послуг для їх побудови в заводських класах. набагато чистіший підхід.

Це від того, хто має обмежений вплив на вищезазначені малюнки, тому я також хотів би почути думки / переживання інших з цього приводу!

Більше читання


Дякую за приємне пояснення. Моє запитання було "Чому в ядрі є два способи отримати доступ до помічника?" тож це трохи поза темою, але це очистило деякі інші сумніви у мене. :) Дякую.
Маріус

Я б, напевно, сказав, що це просто щось, що ще не відремонтоване ще. Або це, або це може бути простотою у використанні. Вимагати від споживачів завжди вводити всі свої залежності в контролер можна розглядати як контрпродуктивне, особливо при виконанні RAD. Надання споживачам обох способів доступу до залежностей дозволить використовувати підхід RAD, але все ж дозволяє іншим людям чітко визначити свої залежності, якщо вони цього хочуть.
Айдін Хассан

5

Ще один спосіб використання помічника (у шаблонах):

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]')->getMethodName();

Я сподіваюся, що це буде корисно, якщо ви ще не знали.


це якимось чином схоже на використання диспетчера об'єктів. Не впевнений, що це найкраща ідея.
Маріус

1
Наведений вище метод призначений лише для шаблонів, наскільки я знаю. Менеджер об'єктів використовується в контролерах, блоках, моделях тощо
rbncha

1
Це не в тому ж шарі, що і код, оскільки немає кодових залежностей від шаблонів. Шаблони є лише споживачами і не забруднюють клієнтів порушеною інкапсуляцією.
demonkoryu

Я не знаю, що демонстратор намагається сказати. Але найкращий спосіб викликати помічника будь-якого модуля - це. Це Маженто. Як кажуть, кожен блок / код розділу призначений для виклику / зміни, не торкаючись ядра. Отже, все взаємопов’язано або має залежності.
rbncha

2

Хоча це старе питання, я не впевнений, чи отримав Маріус свою відповідь. Я вірю, що Маріус може відповісти на це краще. Я хотів би відповісти на це коротко. Чому Magento 2 пропонує використовувати DI замість помічника?

  • Можливість / простота ізоляції при тестуванні одиниць
  • Явно визначають залежності класу
  • Сприяння гарному дизайну (наприклад, принцип єдиної відповідальності (SRP))
  • Використання DI у своєму модулі зменшує ризик помилок несумісності, коли Magento змінює базову реалізацію цих інтерфейсів. Це важлива концепція, яку слід розуміти розробникам розширень.

Чому ядро ​​M2 може не використовувати DI в деяких випадках?

  • Зменшення кількості занять
  • Не створювати зайвих інтерфейсів
  • Немає ризику невідповідності помилок

Хоча модуль каталогі Core був використаний помічником, він широко використовував DI. У своєму дослідженні я виявив, що Magento 2 використовував декілька функцій у допоміжних файлах Core Catalog, які не підходять для контрактів на обслуговування.

Якщо потрібно явно використовувати клас, визначений Magento (наприклад, \ Magento \ Каталог \ Модель \ Продукт), зробіть неявну залежність явною залежно від конкретної реалізації замість інтерфейсу контракту на обслуговування.

Безперечно, розробник розширень повинен використовувати DI замість Magento1, як Helper. При впровадженні згідно з настановами Magento 2 випадання обмежені. При порушенні рекомендацій трапляються проблеми.


Так, я отримав свою відповідь тим часом. Але дякую, що знайшли час для відповіді. Це цінна інформація для людей, які шукають це в Інтернеті.
Маріус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.