événements observateurs sur mesure
-
16-10-2019 - |
Question
J'ai créé une intégration API avec un détaillant tiers. J'ai créé mes propres appels Mage::dispatchEvent
avant et après la communication. J'utilise surtout ces derniers pour le mode enregistrement / debug, mais j'ai maintenant la possibilité de les utiliser pour manipuler les données d'une autre, le module vaguement lié qui utiliseraient également cette API.
Dans le exemple ci-dessous est-il possible de manipuler $post_string
dans ce champ local basé sur ce que mon observateur peut faire?
Mage::dispatchEvent('my_api_delete_before', array('post_string'=>$post_string, 'my_cart'=>$this));
$result = $this->doApiCommunication($post_string);
Mage::dispatchEvent('my_api_delete_after', array('post_string'=>$post_string, 'result'=>$result, 'product'=>$product, 'cart_item_id'=>$_item->cartItemId));
La solution
Si $post_string
est une chaîne, alors non. Les changements effectués à dans la classe d'observateurs ne seraient pas présentés dans ce champ parce que les chaînes ne sont pas passés par référence aux fonctions.
Il existe plusieurs solutions pour cela:
rapide mais pas recommandé:
PHP ne vous donne une solution de contournement, en forçant la chaîne à passer par référence à la fonction en ajoutant un &
avant le nom de la variable, comme suit:
Mage::dispatchEvent('my_api_delete_before', array('post_string'=>&$post_string, 'my_cart'=>$this));
Mais la raison n'est pas recommandé, comme @dedmeet a dit dans son commentaire :
à l'aide du temps d'appel passe par référence est pas pris en charge depuis la version PHP 5.4.0
Directement à partir du manuel PHP :
Remarque: Il n'y a aucun signe de référence sur un appel de fonction - uniquement sur la fonction Définitions. Les définitions de fonction sont les seuls suffisante pour passer correctement l'argument par référence. PHP 5.3.0, vous obtiendrez un avertissement en disant que « passage par référence temps d'appel » est dépréciée lorsque vous utilisez & dans foo (& $ a) ;. Et à partir de PHP 5.4.0, passe par référence temps d'appel était retiré, afin de l'utiliser soulèvera une erreur fatale.
Voici donc comment le faire d'une manière qui est
Cleaner et recommandé:
Une meilleure solution serait de créer une Varien_Object
parce que les classes sont toujours passés par référence. Et toute classe qui étend Varien_Object
et le Varien_Object
lui-même, vous donne la possibilité d'utiliser les accesseurs que vous trouverez autour Mangento.
$obj = new Varien_Object();
// Set a value for data variable
$obj->setFoo($bar);
// The previous function is the same as the following:
// In fact, the previous function will call setData with 'foo' and $bar as its paramteres
$obj->setData('foo', $bar);
// To get the value of 'foo' you will need to call any of the following functions:
$obj->getFoo();
$obj->getData('foo');
Donc, pour mettre en œuvre le Varien_object
dans l'exemple de l'OP:
class Foo_Bar_Model_Communicator{
public function someFunction(){
/*
* Assuming that $post_string is getting set here somehow
* before the next line.
*/
$eventData = new Varien_Data();
$eventData->setData('post_string', $post_string);
$eventData->setData('cart', $this);
Mage::dispatchEvent('my_api_delete_before', array('event_data'=>$eventData));
/* In this case, since we sent a Varien_Object as parameter,
* whatever the Observer class does to the object, will be reflected
* here as well.
* We only need to make sure that we get the string back from the
* Varien_Object instead of using $post_string.
*/
$new_post_string = $eventData->getData('post_string');
$result = $this->doApiCommunication($new_post_string);
/*
* We can do the same for the parameters for the next event, but it
* wasn't part of the OP's question and it won't be needed since
* there is no code following the dispatch event.
*
* However it would be a better idea to make the "before" & "after"
* events have the same type of parameters which would be less
* confusing later on.
*/
Mage::dispatchEvent('my_api_delete_after', array('post_string'=>$post_string, 'result'=>$result, 'product'=>$product, 'cart_item_id'=>$_item->cartItemId));
}
}