将数据传递给getChildHtml()或子块上的调用方法


12

我希望能够将数据传递给getChildHtml()调用。原因是,该块的输出取决于产品类型。所以我想将产品传递给getChildHtml,以便它可以决定输出。

我在里面做这个template/checkout/cart/item/default.phtml

理想情况下,呼叫应如下所示:

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

然后,我的模块可以从项目中获取产品类型并显示正确的输出。

由于绝对不可能将数据传递给getChildHtml-无需重写核心块又如何实现这种类型的行为

我目前拥有的两种解决方案如下(都不很有吸引力):

1-创建一个帮助程序,并通过该帮助程序访问html输出,而不是让块和模板将其呈现给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

您可以创建产品类型属性-也许您根据产品类型创建不同的属性?如果您愿意创建自己的积木,我们当然可以朝这个方向提供建议,但这里可能还有其他一些内在的胜利,我正在努力
探寻

嗯,这是我正在访问的产品级别属性,但是显示方式取决于产品类型。与简单产品相比,分组产品将呈现相同的属性。我正在为每种不同的输出方式使用块和模板
Marty Wallace

我用一些我正在考虑但不100%满意的想法更新了我的问题
Marty Wallace

Answers:


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中的所有内容一样)
VictorSchröder,

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);
}

所有这一切将要求将是为每个产品类型不同的块型- ,bundlesimpleconfigurable,。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方面不同的东西。
nevvermind

我从未说过他们做不到;我的意思是,根据定义,小部件需要输入数据才能有条件地显示某些内容。
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();

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.