Pase datos a getChildHtml () o llame al método en el bloque secundario

12

Quiero poder pasar datos a la llamada getChildHtml (). La razón es que la salida del bloque depende de un tipo de producto. Así que quiero pasar el producto al getChildHtml para que pueda decidir sobre la salida.

Estoy haciendo esto por dentro template/checkout/cart/item/default.phtml.

Idealmente, la llamada se vería así:

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

Entonces mi bloque puede obtener el tipo de producto del artículo y mostrar la salida correcta.

Como definitivamente no es posible pasar estos datos getChildHtml, ¿de qué otra manera se puede lograr este tipo de comportamiento sin tener que reescribir el bloque central?

Las dos soluciones que tengo actualmente son las siguientes (ninguna muy atractiva):

1 - Cree un ayudante y acceda a la salida html a través del ayudante en lugar de dejar que un bloque y una plantilla lo procesen $this->helper('my_module')->getItemHtml($_item);

2 - Acceda al bloque secundario y establezca Datos dentro de la plantilla:

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

Creo que, en términos de la arquitectura de Magento, el número 2 es el menor de dos males, pero es muy feo dentro de una plantilla.

Marty Wallace
fuente
¿Puede en su lugar proporcionar los 'datos' en el registro o sesión que utiliza el bloque secundario? ¿Estás usando esto en un iterador? ¿Cuál es el caso de uso?
philwinkle
No creo que el registro ayude aquí, ya que el resultado deseado depende del tipo de producto de los artículos del carrito. Por lo tanto, esto debe pasarse al bloque de alguna manera para que se puedan generar los datos correctos. El caso de uso es mostrar información adicional sobre el artículo del carrito, pero depende del tipo de producto
Marty Wallace
Puede crear atributos de tipo de producto. ¿Quizás cree atributos diferentes según los tipos de producto? Si prefiere crear su propio bloque que sin duda ayudará en esa dirección, pero que puede haber algunos otros elementos de construcción en la victoria aquí que yo estoy tratando de olfatear ...
philwinkle
Bueno, es un atributo de nivel de producto al que estoy accediendo, pero la forma en que se muestra depende del tipo de producto. Un producto agrupado hará que el mismo atributo sea ligeramente diferente al de un producto simple. Estoy usando un bloque y una plantilla para cada sabor de salida diferente
Marty Wallace
He actualizado mi pregunta con algunas ideas que tengo y que estoy contemplando pero con las que no estoy 100% cómodo
Marty Wallace

Respuestas:

3

Puede agregar un método en el bloque padre para buscar el hijo dependiendo del tipo de producto (he visto este tipo de lógica un par de veces en el núcleo o algo similar):

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

Aún así, al ver cómo modifica el diseño xml para agregar bloques secundarios, puede interesarle cómo Magento decidió trabajar con el marcado de representación dependiendo de los tipos de productos en Mage_Sales_Block_Items_Abstract::getItemHtml()y Mage_Checkout_Block_Cart_Abstract::getItemHtml().

nevvermind
fuente
Este método omite la estructura de diseño y produce bloques que están estrechamente acoplados (como todo en Magento ...)
Victor Schröder
12

La solución anterior no funcionará si está mostrando un bloque secundario en foreachbucle.

Para eso necesitas usar el siguiente código:

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

En child.block puedes usar $this->getMyData()para obtener los datos. Usando esta estrategia, el bloque hijo siempre obtendrá los datos más recientes de los padres.

El segundo parámetro de getChildHtml()es $useCache. Establecerlo en falso evita que la primera salida se almacene en caché y obliga a volver a generar el elemento secundario.

Arvind07
fuente
4

Un bloque que puede recibir datos se llama un widget ; aunque esto se puede hacer a través de múltiples definiciones de bloque (basadas en las propiedades de $_item).

Magento hace algo muy similar en el núcleo al cargar el bloque de método de pago basado en el código corto del método:

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

Podrías hacer lo mismo con este pseudocódigo:

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

Todo lo que se requiere sería tener un tipo de bloque diferente para cada tipo de producto - bundle, simple, configurable, virtual, grouped. No tan mal, de verdad.

Si realmente desea usar un widget , sería algo como el efecto de su segunda idea en su pregunta editada:

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

Crear un widget probablemente fuera del alcance de esta respuesta, pero no es terriblemente difícil y tiene la ventaja de poder reutilizarse para bloques CMS, aunque para su caso de uso no creo que sea aplicable.

Para obtener más información sobre cómo crear un widget:

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

philwinkle
fuente
No estoy 100% convencido de que este sea un buen enfoque para esto, que no he aceptado la respuesta.
Marty Wallace,
1
¿Solo un bloque de widgets puede recibir datos? ¿Qué quieres decir? Todos los bloques pueden recibir datos. Un widget es algo diferente en términos de Magento.
nevvermind
Nunca dije que no podían; Estoy diciendo, por definición, un widget requiere la entrada de datos para mostrar algo condicionalmente.
philwinkle
0

Para Magento 2, puedes usar

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

Para obtener los datos,

$block->getMyData();

Keyur Shah
fuente