Киев
             15 сентября 2012




Magento DI
Software Entropy

Pull-approach and its problems

Push-approach

Magento Object Manager
Software entropy
Software entropy cycle
Pull-approach
Mage::getModel(“Mage_Cms_Model_Page”)

Mage::getSingleton(“Mage_Cms_Model_Page”)
class Mage_Cms_Model_Page
{
   public function __construct()
   {
     $this->_idFieldName = Mage::getResourceSingleton($this->_resourceName);
   }

    public function getAvailableStatuses()
    {
      $statuses = new Varien_Object(array(
          self::STATUS_ENABLED => Mage::helper('Mage_Cms_Helper_Data')->__('Enabled')
          self::STATUS_DISABLED => Mage::helper('Mage_Cms_Helper_Data')        ->__(„Disabled')
      ));
      Mage::dispatchEvent('cms_page_get_available_statuses', array('statuses' => $statuses));
    }
}
class Mage_Cms_Model_PageTest extends PHPUnit_Framework_TestCase
{
   public function setUp()
   {
     $this->_page = new Mage_Cms_Model_Page();
   }
}
class Mage_Cms_Model_PageTest extends PHPUnit_Framework_TestCase
{
   public function setUp()
   {
        Mage::setResourceSingleton(„Page_Resource‟, $this->getMock(„Page_Resource‟));
        $this->_page = new Mage_Cms_Model_Page();
    }

    public function testProcessDoesSomething()
    {
      Mage::setHelper(„Mage_Cms_Helper_Data‟, $this->getMock(„Mage_Cms_Helper_Data‟));
      $this->assertSomething($this->_page->process());
    }
}
Mage::getXXX() ===
Push-approach
class Mage_Core_Model_Abstract
{
   public function __construct(array $data = array())
   {
     parent::__construct($data);
     $this->_construct();
   }
}
class Mage_Core_Model_Abstract
{
   public function __construct(
     Mage_Core_Model_Event_Manager $eventDispatcher,
     Mage_Core_Model_Cache $cacheManager,
     Mage_Core_Model_Resource_Abstract $resource = null,
     Varien_Data_Collection_Db $resourceCollection = null,
     array $data = array()
   ){
     $this->_eventDispatcher = $eventDispatcher;
     $this->_cacheManager = $cacheManager;
     $this->_resource = $resource;
     $this->_resourceCollection = $resourceCollection;

        parent::__construct($data);
        $this->__construct();
    }
}
Mage::getXXX()


Mage_Some_Class::__construct()
   Magento_ObjectManager
Magento Object Manager
interface Magento_ObjectManager
{
    public function get($className, $arguments);

    public function create($className, $arguments);
}
ZendDi
class Mage_Core_Model_Abstract
{
   public function __construct(
     Mage_Core_Model_Event_Manager $eventDispatcher,
     Mage_Core_Model_Cache $cacheManager,
     Mage_Core_Model_Resource_Abstract $resource = null,
     Varien_Data_Collection_Db $resourceCollection = null,
     array $data = array()
   ){
     $this->_eventDispatcher = $eventDispatcher;
     $this->_cacheManager = $cacheManager;
     $this->_resource = $resource;
     $this->_resourceCollection = $resourceCollection;

        parent::__construct($data);
        $this->__construct();
    }
}
<config>
  <global>
    <di>
       <Mage_Core_Model_Cache>
          <parameters>
            <cacheDir>/path/to/cache/dir</cacheDir>
          </parameters>
       </Mage_Core_Model_Cache>
    </di>
  </global>
</config>
<di>
  <Magento_Data_Structure>
     <shared>0</shared>
  </Magento_Data_Structure>
</di>
public function __construct(Some_Interface $processor)
<adminhtml>
  <di>
     <preferences>
       <Some_Interface>Some_Backend_Implementation</Some_Interface>
     </preferences>
  </di>
</adminhtml>
<api>
  <di>
     <preferences>
       <Some_Interface>Some_Api_Implementation</Some_Interface>
     </preferences>
  </di>
</api>
INJECTABLES               -   NON-INJECTABLES
 Varien_Db_Adapter
                               Mage_Catalog_Model_Product
 Mage_Core_Model_Cache
                               Mage_Wishlist_Model_Wishlist
 Mage_Core_Model_Config
class Varien_Data_Collection
{
   //...
    public function getNewEmptyItem()
   {
       return Mage::getModel($this->_itemObjectClass);
   }
    //...
}
class Varien_Data_Collection
{
   public function __construct(Magento_ObjectFactory $factory)
   {
     $this->_itemFactory = $factory;
   }

    //...
    public function getNewEmptyItem()
    {
        return $this->_itemFactory->create();
    }
    //...
}
class Mage_Catalog_Model_Product_Factory implements Magento_ObjectManager_Factory
{
   protected $_objectManager;

    public function __construct(Magento_ObjectManager $objectManager)
    {
      $this->_objectManager = $objectManager;
    }

    public function createFromArray(array $arguments = array())
    {
      return $this->_objectManager->create('Mage_Catalog_Model_Product', $arguments);
    }
}
class Mage_Review_Model_Observer
{
   public function processDeletedProduct (Varien_Event_Observer $observer)
   {
     $productId = $observer->getEvent()->getProduct()->getId();

        if ($productId) {
           Mage::getResourceSingleton('Mage_Review_Model_Resource_Review')
              ->deleteReviewsByProductId($productId);
        }
    }
}
class Mage_Review_Model_Observer
{
   public function __construct(Mage_Review_Model_Resource_Review $review)
   {
     $this->_reviewResource = $reviewResource;
   }

    //...
}
<di>
  <Mage_Review_Model_Observer>
     <parameters>
       <review>
          Mage_Review_Model_Resource_Review_Proxy
       </review>
     </parameters>
  </ Mage_Review_Model_Observer >
</di>
class Mage_Review_Model_Resource_Review_Proxy
   extends Mage_Review_Model_Resource_Review
{
   public function __construct(Magento_ObjectManager $objectManager)
   {
     $this->_objectManager = $objectManager;
   }

    public function deleteReviewByProductId($productId)
    {
      return $this->_objectManager
        ->get('Mage_Review_Model_Resource_Review ')
        ->deleteReviewByProductId();
    }
}

Magento Dependency Injection

  • 1.
    Киев 15 сентября 2012 Magento DI
  • 2.
    Software Entropy Pull-approach andits problems Push-approach Magento Object Manager
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    class Mage_Cms_Model_Page { public function __construct() { $this->_idFieldName = Mage::getResourceSingleton($this->_resourceName); } public function getAvailableStatuses() { $statuses = new Varien_Object(array( self::STATUS_ENABLED => Mage::helper('Mage_Cms_Helper_Data')->__('Enabled') self::STATUS_DISABLED => Mage::helper('Mage_Cms_Helper_Data') ->__(„Disabled') )); Mage::dispatchEvent('cms_page_get_available_statuses', array('statuses' => $statuses)); } }
  • 8.
    class Mage_Cms_Model_PageTest extendsPHPUnit_Framework_TestCase { public function setUp() { $this->_page = new Mage_Cms_Model_Page(); } }
  • 9.
    class Mage_Cms_Model_PageTest extendsPHPUnit_Framework_TestCase { public function setUp() { Mage::setResourceSingleton(„Page_Resource‟, $this->getMock(„Page_Resource‟)); $this->_page = new Mage_Cms_Model_Page(); } public function testProcessDoesSomething() { Mage::setHelper(„Mage_Cms_Helper_Data‟, $this->getMock(„Mage_Cms_Helper_Data‟)); $this->assertSomething($this->_page->process()); } }
  • 10.
  • 11.
  • 12.
    class Mage_Core_Model_Abstract { public function __construct(array $data = array()) { parent::__construct($data); $this->_construct(); } }
  • 13.
    class Mage_Core_Model_Abstract { public function __construct( Mage_Core_Model_Event_Manager $eventDispatcher, Mage_Core_Model_Cache $cacheManager, Mage_Core_Model_Resource_Abstract $resource = null, Varien_Data_Collection_Db $resourceCollection = null, array $data = array() ){ $this->_eventDispatcher = $eventDispatcher; $this->_cacheManager = $cacheManager; $this->_resource = $resource; $this->_resourceCollection = $resourceCollection; parent::__construct($data); $this->__construct(); } }
  • 14.
  • 15.
  • 16.
    interface Magento_ObjectManager { public function get($className, $arguments); public function create($className, $arguments); }
  • 18.
  • 19.
    class Mage_Core_Model_Abstract { public function __construct( Mage_Core_Model_Event_Manager $eventDispatcher, Mage_Core_Model_Cache $cacheManager, Mage_Core_Model_Resource_Abstract $resource = null, Varien_Data_Collection_Db $resourceCollection = null, array $data = array() ){ $this->_eventDispatcher = $eventDispatcher; $this->_cacheManager = $cacheManager; $this->_resource = $resource; $this->_resourceCollection = $resourceCollection; parent::__construct($data); $this->__construct(); } }
  • 20.
    <config> <global> <di> <Mage_Core_Model_Cache> <parameters> <cacheDir>/path/to/cache/dir</cacheDir> </parameters> </Mage_Core_Model_Cache> </di> </global> </config>
  • 21.
    <di> <Magento_Data_Structure> <shared>0</shared> </Magento_Data_Structure> </di>
  • 22.
  • 23.
    <adminhtml> <di> <preferences> <Some_Interface>Some_Backend_Implementation</Some_Interface> </preferences> </di> </adminhtml> <api> <di> <preferences> <Some_Interface>Some_Api_Implementation</Some_Interface> </preferences> </di> </api>
  • 24.
    INJECTABLES - NON-INJECTABLES Varien_Db_Adapter Mage_Catalog_Model_Product Mage_Core_Model_Cache Mage_Wishlist_Model_Wishlist Mage_Core_Model_Config
  • 25.
    class Varien_Data_Collection { //... public function getNewEmptyItem() { return Mage::getModel($this->_itemObjectClass); } //... }
  • 26.
    class Varien_Data_Collection { public function __construct(Magento_ObjectFactory $factory) { $this->_itemFactory = $factory; } //... public function getNewEmptyItem() { return $this->_itemFactory->create(); } //... }
  • 27.
    class Mage_Catalog_Model_Product_Factory implementsMagento_ObjectManager_Factory { protected $_objectManager; public function __construct(Magento_ObjectManager $objectManager) { $this->_objectManager = $objectManager; } public function createFromArray(array $arguments = array()) { return $this->_objectManager->create('Mage_Catalog_Model_Product', $arguments); } }
  • 28.
    class Mage_Review_Model_Observer { public function processDeletedProduct (Varien_Event_Observer $observer) { $productId = $observer->getEvent()->getProduct()->getId(); if ($productId) { Mage::getResourceSingleton('Mage_Review_Model_Resource_Review') ->deleteReviewsByProductId($productId); } } }
  • 29.
    class Mage_Review_Model_Observer { public function __construct(Mage_Review_Model_Resource_Review $review) { $this->_reviewResource = $reviewResource; } //... }
  • 30.
    <di> <Mage_Review_Model_Observer> <parameters> <review> Mage_Review_Model_Resource_Review_Proxy </review> </parameters> </ Mage_Review_Model_Observer > </di>
  • 31.
    class Mage_Review_Model_Resource_Review_Proxy extends Mage_Review_Model_Resource_Review { public function __construct(Magento_ObjectManager $objectManager) { $this->_objectManager = $objectManager; } public function deleteReviewByProductId($productId) { return $this->_objectManager ->get('Mage_Review_Model_Resource_Review ') ->deleteReviewByProductId(); } }