Magento – Magento 2: Use a model with a dynamic name through DI

dimagento2

i have one situation where i need to load need model dynamically

i followed below steps it work great same way like layersPool in catalog module

but they used objectManager as per magento we should not use objectManager so please let me know how to solve this situation without objectManager, we can solve this issue by sending data in di.xml as object instated of string but it will init all class when you call that layerpool so dont use object

di.xml

<type name="Magento\Catalog\Model\Layer\Resolver">
    <arguments>
        <argument name="layersPool" xsi:type="array">
            <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\Category</item>
            <item name="search" xsi:type="string">Magento\Catalog\Model\Layer\Search</item>
        </argument>
    </arguments>
</type>

vendor\magento\module-catalog\Model\Layer\Resolver.php

<?php
/**
 *
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Catalog\Model\Layer;

class Resolver
{
    const CATALOG_LAYER_CATEGORY = 'category';
    const CATALOG_LAYER_SEARCH = 'search';

    /**
     * Catalog view layer models list
     *
     * @var array
     */
    protected $layersPool;

    /**
     * Filter factory
     *
     * @var \Magento\Framework\ObjectManagerInterface
     */
    protected $objectManager;

    /**
     * @var \Magento\Catalog\Model\Layer
     */
    protected $layer = null;

    /**
     * @param \Magento\Framework\ObjectManagerInterface $objectManager
     * @param array $layersPool
     */
    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectManager,
        array $layersPool
    ) {
        $this->objectManager = $objectManager;
        $this->layersPool = $layersPool;
    }

    /**
     * Create Catalog Layer by specified type
     *
     * @param string $layerType
     * @return void
     */
    public function create($layerType)
    {
        if (isset($this->layer)) {
            throw new \RuntimeException('Catalog Layer has been already created');
        }
        if (!isset($this->layersPool[$layerType])) {
            throw new \InvalidArgumentException($layerType . ' does not belong to any registered layer');
        }
        $this->layer = $this->objectManager->create($this->layersPool[$layerType]);
    }

    /**
     * Get current Catalog Layer
     *
     * @return \Magento\Catalog\Model\Layer
     */
    public function get()
    {
        if (!isset($this->layer)) {
            $this->layer = $this->objectManager->create($this->layersPool[self::CATALOG_LAYER_CATEGORY]);
        }
        return $this->layer;
    }
}

in needed place you can call

 $this->layerResolver->create('category');

in future add option in di and call it any where and also we can use get if you dont want create a object also

but how to solve this issue with out objectManager

Best Answer

finally i got the answer in di.xml use factory and in reader use create it will be some thing like this

<type name="Magento\Catalog\Model\Layer\Resolver">
    <arguments>
        <argument name="layersPool" xsi:type="array">
            <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\CategoryFactory</item>
            <item name="search" xsi:type="string">Magento\Catalog\Model\Layer\SearchFactory</item>
        </argument>
    </arguments>
</type

in reader file use

public function create($layerType)
    {
        return $this->layersPool[$layerType]->create();
    }

so with out object manger we can call dynamic class from DI

Related Topic