I'm developing a Magento 1 module that will be extended by other modules. Here I will call the parent module as parent
and the "child" module (the module that will extend the classes from parent
) as child
.
I have an abstract class declared for the parent
that has an abstract method called loadExternalItem
. This method loads an external item (like a product) from an external source. For the child
module in this case, that external source is an ERP API that is called in this method to retrieve a product:
<?php
class Child_Module_Model_Entity_Product extends Parent_Module_Model_Entity_Abstract
{
/** Inherited from Parent_Module_Model_Entity_Abstract */
public function loadExternalItem($item)
{
$query = array("query_parameters" => array("id" => $item->getId()));
$response = Mage::getModel("child/api_request")
->make("GET", "PRODUCT_BY_ID", $query);
return $response->getItemFromResponse();
}
}
My question is: where (in the parent
module) shoud I dispatch my event (say my_custom_event
) in a way that all modules that extends loadExternalItem
run it without specifying it in the inherited method's body?
Anyway to do that with abstract methods
? Only way I can think is to not declare the method as abstract and call the dispatch event in the body of the parent
method:
<?php
class Parent_Module_Model_Entity_Abstract extends Mage_Core_Model_Abstract
{
public function loadExternalItem($item)
{
Mage::dispatchEvent("my_custom_event");
}
}
And call it at the end of the child
's method:
<?php
class Child_Module_Model_Entity_Product extends Parent_Module_Model_Entity_Abstract
{
/** Inherited from Parent_Module_Model_Entity_Abstract */
public function loadExternalItem($item)
{
$query = array("query_parameters" => array("id" => $item->getId()));
$response = Mage::getModel("child/api_request")
->make("GET", "PRODUCT_BY_ID", $query);
$responseItem = $response->getItemFromResponse();
parent::importExternalItem($item); /** Calls the dispatch event */
return $responseItem;
}
}
But it seems "hacky" and not so efficient, because the main reason is to avoid that developers working in a new child module forget to dispatch this event, and in this case they might as well forget to call the parent::importExternalItem()
.
The standard way to do parent-child inherited method is like this:
Parent:
<?php
abstract class Parent_Module_Model_Entity_Abstract extends Mage_Core_Model_Abstract
{
/**
* @param Some_Item $item
* @return $this
*/
protected function _loadExternalItem($item)
{
return $this;
}
/**
* @param Some_Item $item
* @return $this
*/
public function loadExternalItem($item)
{
// Mage::dispatchEvent("parent_entity_load_external_item_before", ['some_item' => $item]);
$this->_loadExternalItem($item);
Mage::dispatchEvent("parent_entity_load_external_item_after", ['some_item' => $item]);
return $this;
}
}
Child:
<?php
class Child_Module_Model_Entity_Product extends Parent_Module_Model_Entity_Abstract
{
/**
* @inheritdoc
*/
protected function _loadExternalItem($item)
{
$query = array("query_parameters" => array("id" => $item->getId()));
$response = Mage::getSingleton("child/api_request")
->make("GET", "PRODUCT_BY_ID", $query);
$responseItem = $response->getItemFromResponse();
$this->setExternalItem($responseItem); // magic setter-getter
return parent::_loadExternalItem($item);
}
}
To call:
$item = Mage::getModel('child/product')
->load(123)
->loadExternalItem($item)
->getExternalItem();