Passer des données à getChildHtml () ou appeler la méthode sur le bloc enfant

12

Je veux pouvoir passer des données à l'appel getChildHtml (). La raison en est que la sortie du bloc dépend d'un type de produit. Je veux donc passer le produit au getChildHtml afin qu'il puisse décider de la sortie.

Je fais ça à l'intérieur template/checkout/cart/item/default.phtml.

Idéalement, l'appel devrait ressembler à:

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

Ensuite, mon bloc peut obtenir le type de produit de l'article et afficher la sortie correcte.

Puisqu'il n'est certainement pas possible de transmettre ces données à getChildHtml- comment autrement ce type de comportement peut-il être obtenu sans avoir à réécrire le bloc de base

Les deux solutions que j'ai actuellement sont les suivantes (ni très attractives):

1 - Créez un assistant et accédez à la sortie html via l'aide au lieu de laisser un bloc et un modèle le rendre ala $this->helper('my_module')->getItemHtml($_item);

2 - Accédez au bloc enfant et définissez-y les données à l'intérieur du modèle:

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

Je pense qu'en termes d'architecture Magento, le numéro 2 est le moindre de deux maux, mais il est sacrément laid à l'intérieur d'un modèle.

Marty Wallace
la source
Pouvez-vous plutôt fournir les «données» dans le registre ou la session que le bloc enfant utilise? L'utilisez-vous dans un itérateur? Quel est le cas d'utilisation?
philwinkle
Je ne pense pas que le registre aiderait ici car la sortie souhaitée dépend du type de produit des articles du panier. Donc, cela doit être transmis au bloc d'une certaine manière afin que les données correctes puissent être sorties. Le cas d'utilisation affiche des informations supplémentaires sur l'article du panier, mais cela dépend du type de produit
Marty Wallace
Vous pouvez créer des attributs de type de produit - peut-être créez-vous des attributs différents en fonction des types de produits? Si vous préférez créer votre propre bloc, nous pouvons certainement vous conseiller dans cette direction, mais il peut y avoir une autre victoire intégrée ici que j'essaie de flairer ...
philwinkle
Eh bien, c'est un attribut au niveau du produit auquel j'accède, mais la façon dont il s'affiche dépend du type de produit. Un produit groupé rendra le même attribut légèrement différemment qu'un produit simple. J'utilise un bloc et un modèle pour chaque saveur différente de la sortie
Marty Wallace
J'ai mis à jour ma question avec quelques idées que
Marty Wallace

Réponses:

3

Vous pouvez ajouter une méthode sur le bloc parent pour récupérer l'enfant en fonction du type de produit (j'ai vu ce type de logique plusieurs fois dans le noyau ou quelque chose de similaire):

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

Cependant, en voyant comment vous modifiez la mise en page XML pour ajouter des blocs enfants, vous pouvez être intéressé par la façon dont Magento a décidé de travailler avec le balisage de rendu en fonction des types de produits dans Mage_Sales_Block_Items_Abstract::getItemHtml()et Mage_Checkout_Block_Cart_Abstract::getItemHtml().

Nevermind
la source
Cette méthode contourne la structure de la disposition et produit des blocs qui sont étroitement couplés (comme tout dans Magento ...)
Victor Schröder
12

La solution ci-dessus ne fonctionnera pas si vous affichez un bloc enfant en foreachboucle.

Pour cela, vous devez utiliser le code suivant:

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

Dans child.block, vous pouvez utiliser $this->getMyData()pour obtenir les données. En utilisant cette stratégie, le bloc enfant obtiendra toujours les dernières données du parent.

Le deuxième paramètre de getChildHtml()est $useCache. La définition de false empêche la première sortie d'être mise en cache et force le rendu de l'enfant.

Arvind07
la source
4

Un bloc qui peut recevoir des données est appelé un widget ; bien que cela puisse être fait via plusieurs définitions de blocs (en fonction des propriétés de $_item).

Magento fait quelque chose de très similaire dans le noyau en chargeant le bloc de méthode de paiement basé sur le code court de la méthode:

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

Vous pouvez faire de même avec ce pseudo-code:

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

Tout ce qui nécessiterait serait d'avoir un type de bloc différent pour chaque type de produit - bundle, simple, configurable, virtual, grouped. Pas si mal, vraiment.

Si vous voulez vraiment utiliser un widget - ce serait quelque chose à l'effet de votre deuxième idée dans votre question modifiée:

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

Créer un widget probablement hors du champ de cette réponse - mais ce n'est pas très difficile, et a l'avantage de pouvoir être réutilisé pour les blocs CMS, bien que pour votre cas d'utilisation, je ne pense pas que cela soit applicable.

Pour plus d'informations sur la création d'un widget:

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

philwinkle
la source
Je ne suis pas convaincu à 100% qu'il s'agit d'une bonne approche à laquelle je n'ai pas accepté la réponse.
Marty Wallace,
1
Seul un bloc widget peut recevoir des données? Que voulez-vous dire? Tous les blocs peuvent recevoir des données. Un widget est quelque chose de différent en termes de Magento.
Nevermind
Je n'ai jamais dit qu'ils ne pouvaient pas; Je dis, par définition, un widget nécessite une entrée de données pour afficher quelque chose de manière conditionnelle.
philwinkle
0

Pour Magento 2, vous pouvez utiliser

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

Pour obtenir les données,

$block->getMyData();

Keyur Shah
la source