Magento, Composer and Dependency Injection

Recently I found an information about Composer installer for Magento. I explored this a little bit and I managed to include some other packages (Monolog) and Symfony’s bundles into magento installation. To allow easy configuration I included also Symfony’s Dependency Injector.
How to use it?
  1. Define composer.json in root dir
    {
        "minimum-stability"
    : "dev",
        "require"
    : {
            "monolog/monolog"
    : "dev-master",
        "magento-hackathon/magento-composer-installer"
    : "dev-master",
            "symfony/dependency-injection"
    : "dev-master",
            "symfony/yaml"
    : "dev-master",
            "symfony/config"
    : "dev-master",
            "symfony/monolog-bundle"
    : "dev-master",
            "mlehner/gelf-php"
    : "dev-master"
        },
        "repositories"
    : [
            {
                "type"
    : "composer",
                "url"
    : "http://packages.firegento.com"
            }
        ],
        "extra":{
            "magento-root-dir"
    : "src/"
        }
    }
  2. Download composer
  3. mkdir bin
    curl -s https://getcomposer.org/installer | php -- --install-dir=bin
    bin/composer.phar install
  4. Create Your_Core_Model_Config
    <?php
    use Symfony\Component\DependencyInjection\ContainerAwareInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\Config\FileLocator;
    use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
    use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
    use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;

    class Your_Core_Model_Config extends Mage_Core_Model_Config
    {
        /**
         *
         * @var Symfony\Component\DependencyInjection\Container
         */

        protected $container = null;
       
        /**
         * Get model class instance.
         *
         * Example:
         * $config->getModelInstance('catalog/product')
         *
         * Will instantiate Mage_Catalog_Model_Mysql4_Product
         *
         * @param string $modelClass
         * @param array|object $constructArguments
         * @return Mage_Core_Model_Abstract
         */

        public function getModelInstance($modelClass='', $constructArguments=array())
        {
            $className = $this->getModelClassName($modelClass);
            if (class_exists($className)) {
                Varien_Profiler::start('CORE::create_object_of::'.$className);
                $obj = new $className($constructArguments);
                if ($obj instanceof ContainerAwareInterface) {
                    $obj->setContainer($this->getContainer());
                }
                Varien_Profiler::stop('CORE::create_object_of::'.$className);
                return $obj;
            } else {
                #throw Mage::exception('Mage_Core', Mage::helper('core')->__('Model class does not exist: %s.', $modelClass));
               return false;
            }
        }
       
        public function getContainer()
        {
            if ($this->container == null) {
                $container = new ContainerBuilder();
               
                $bundles = array (
                    new Symfony\Bundle\MonologBundle\MonologBundle(),
                );
               
                $extensions = array();
                foreach ($bundles as $bundle) {
                    if ($extension = $bundle->getContainerExtension()) {
                        $container->registerExtension($extension);
                        $extensions[] = $extension->getAlias();
                    }
                }
               
                foreach ($bundles as $bundle) {
                    $bundle->build($container);
                }
               
                $loader = new YamlFileLoader($container, new FileLocator($this->getOptions()->getEtcDir()));
                $loader->load('services.yml');
                $loader->load('config.yml');
               
                // ensure these extensions are implicitly loaded
                $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));

                $container->compile();
               
                $this->container = $container;
               
            }
            return $this->container;
        }
    }

    In app/Mage.php change Mage_Core_Model_Config to Your_Core_Model_Config in run and app methods.

  5. Define app/etc/services.yml:
    parameters:
      monolog.handler.chromephp.class
    : Monolog\Handler\ChromePHPHandler
      monolog.handler.firephp.class
    : Monolog\Handler\FirePHPHandler

    and app/etc/config.yml

    monolog:
        handlers
    :
            main
    :
                type
    : stream
                path
    : "var/log/debug.log"
                level
    : debug
            gelf
    :
                type
    : gelf
                level
    : debug
                publisher
    :
                  hostname
    : localhost
            chromephp
    :
                type
    : chromephp
                level
    : debug
            firephp
    :
                type
    : firephp
                level
    : info
  6. Now you can use it in your classes:
    <?php
    use Symfony\Component\DependencyInjection\ContainerAwareInterface;
    use Symfony\Component\DependencyInjection\ContainerInterface;

    class Your_Module_Model_Something extends Mage_Core_Model_Abstract implements ContainerAwareInterface
    {
        protected $container;

        public function setContainer(ContainerInterface $container = null)
        {
            $this->container = $container;
        }

        public function log($data)
        {
            $logger = $this->container->get('logger');
            $logger->debug($data);
        }
    }
Why dependency injection is cool you can find in papers below
Resources
https://github.com/magento-hackathon/magento-composer-installer
https://packagist.org/
http://symfony.com/doc/current/components/dependency_injection/index.html
http://symfony.com/doc/current/book/service_container.html
http://martinfowler.com/articles/injection.html
Categories: Magento, Symfony
  • Alessandro Ronchi

    Dear Piotr,
    maybe you can be interested in my Magento Monolog integration module, it’s at its very early stages, I still need to complete it that but maybe it can be helpful.

    https://github.com/aleron75/magemonolog

    Regards, Alessandro