Передайте дані getChildHtml () або метод виклику на дочірнім блоці


12

Я хочу мати можливість передавати дані на виклик getChildHtml (). Причина полягає в тому, що вихід блоку залежить від типу продукту. Тому я хочу передати продукт getChildHtml, щоб він міг вирішити вихід.

Я роблю це всередині template/checkout/cart/item/default.phtml.

В ідеалі дзвінок виглядатиме так:

echo $this->getChildHtml('child_block_name', $_item);

Тоді мій блок може отримати тип продукту з елемента та відобразити правильний вихід.

Оскільки, безумовно, неможливо передати ці дані getChildHtml- як ще можна досягти такого типу поведінки без необхідності переписувати основний блок

Наразі у мене два рішення (ні дуже привабливі):

1 - Створіть помічник і отримайте доступ до виводу HTML через helper замість того, щоб блок і шаблон відображали його ala $this->helper('my_module')->getItemHtml($_item);

2 - Отримайте доступ до дочірнього блоку та встановіть Дані на нього всередині шаблону:

 $this->getChild('child_name')->setData('item', $_item);
 echo $this->getChildHtml('child_name')

Я думаю, що з точки зору архітектури Magento, число 2 - це менше, ніж два злини, але це потворно дивиться всередині шаблону.


Чи можете ви натомість надати "дані" в реєстрі чи сеансі, якими користується дочірній блок? Ви використовуєте це в ітераторі? Який випадок використання?
philwinkle

Я не думаю, що реєстр допоможе тут, оскільки бажаний вихід залежить від типу продукту кошика. Отже, це необхідно певним чином передавати до блоку, щоб можна було вивести правильні дані. У випадку використання відображається додаткова інформація про товар у кошику, але це залежить від типу товару
Marty Wallace

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

Ну, це атрибут рівня продукту, до якого я отримую доступ, але спосіб його відображення залежить від типу продукту. Згрупований продукт надасть той самий атрибут трохи інакше, ніж, наприклад, простий продукт. Я використовую блок і шаблон для кожного різного аромату випуску
Марті Уоллес

Я оновив своє запитання з деякими ідеями, про які я замислююся, але мені це не на 100% комфортно
Марті Уоллес

Відповіді:


3

Ви можете додати метод до батьківського блоку, щоб отримати дитину залежно від типу продукту (я подібну логіку я бачив кілька разів у ядрі чи щось подібне):

class ParentBlock 
{
    public function getIntuitiveNameChild($item)
    {
        return $this->getChild("intuitive_child")
                    ->setProductType($item->getProductType()) 
                    // You can also decide the product type in this setter, in the Child block.
                    ->setItem($item);
    }

    public function getIntuitiveNameChildDinamically($item)
    {
        return $this->getChild("intuitive_child_" . $item->getProductType())
                    ->setItem($item); 
    }    
}

// parent tpl
// i suggest you avoid getChildHtml(), unless you're certain that methods won't need to be called from the tpl
echo $this->getIntuitiveNameChild($_item)
          // ->someOtherMethod()
          ->toHtml();

Тим не менш, бачачи, як ви змінюєте макет xml для додавання дочірніх блоків, вам може бути цікаво, як Magento вирішив працювати з розміткою рендерінгу залежно від типів продукту в Mage_Sales_Block_Items_Abstract::getItemHtml()і Mage_Checkout_Block_Cart_Abstract::getItemHtml().


Цей метод обходить структуру компонування і створює блоки, які щільно з'єднані (як і все в Magento ...)
Віктор Шредер,

12

Наведене вище рішення не працюватиме, якщо ви відображаєте дочірній блок у foreachциклі.

Для цього вам потрібно використовувати наступний код:

<?php
foreach ($blocks as $block) {
    $this->getChild("child.block")->setData("my_data", $any_data);
    echo $this->getChildHtml('child.block', false);
}
?>

У child.block ви можете використовувати $this->getMyData()для отримання даних. Використовуючи цю стратегію, дочірній блок завжди отримуватиме найновіші дані від батьків.

Другий параметр getChildHtml()є $useCache. Якщо встановити значення false, заважає кешувати перший вихід і змушує дитину знову зробити кеш.


4

Блок, який може приймати дані, називається віджетом ; хоча це можна зробити за допомогою декількох блокових визначень (виходячи із властивостей $_item).

Magento робить щось дуже подібне в ядрі, завантажуючи блок способу оплати на основі короткого коду методу:

<dd>
    <?php echo $this->getChildHtml('payment.method.'.$_code) ?>
</dd>

Ви можете зробити те ж саме з цим псевдокодом:

if($type = $_item->getTypeId()){
    $this->getChildHtml('my.block.' . $type);
}

Все , що потрібно б мати інший тип блоку для кожного типу продукту - bundle, simple, configurable, virtual, grouped. Не так вже й погано, насправді.

Якщо ви дійсно хочете скористатися віджетом - це буде щось до ефекту вашої другої ідеї у вашому відредагованому питанні:

<?php
echo $this->getLayout()->createBlock('yourcompany/widget_class')->setType($_item->getTypeId())->toHtml();

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

Для отримання додаткової інформації про створення віджета:

http://www.magentocommerce.com/knowledge-base/entry/tutorial-creating-a-magento-widget-part-1


Я не на 100% переконаний, що це хороший підхід до цього, на що я не прийняв відповідь.
Марті Уоллес

1
Лише блок віджетів може отримувати дані? Що ви маєте на увазі? Усі блоки можуть приймати дані. Віджет це щось інше , з точки зору Magento.
неввермінд

Я ніколи не казав, що не можуть; Я кажу, за визначенням, віджет вимагає введення даних, щоб відобразити щось умовно.
philwinkle

0

Бо Magento 2можна використовувати

<?php
foreach ($blocks as $block) {
    $block->getChildBlock("child.block")->setData("my_data", $any_data);
    echo $block->getChildHtml('child.block', false);
}
?>

Щоб отримати дані,

$block->getMyData();

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