Magento 2 – Join Product Name to Custom Grid DI Not Working

admingridmagento2

I have an adminhtml custom grid that has a product_id that I need to join the product name to using this product id. I need to use dependency injection to load the attribute manager and store manager so I can do this. Here is the code in my Collection. I have marked ** will not load by the 2 classes I need which when I try to load the page, make it error out. If I comment out the lines that inject the 2 classes, the grid loads fine:

    public function __construct(
    \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
    \Psr\Log\LoggerInterface $logger,
    \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
    \Magento\Framework\Event\ManagerInterface $eventManager,
    \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
    \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null,
    \Magento\Eav\Api\AttributeRepositoryInterface $attrRepoInt, // ** will not load
    \Magento\Store\Model\StoreManagerInterface $storeMan // ** will not load
) {
    $this->_eventManager = $eventManager;
    $this->_attrRepoInt = $attrRepoInt;
    $this->_storeMan = $storeMan;
    parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
}

So the idea is that if I can get access to these 2 classes, then my join code would be like this:

    public function joinProductNames()
{
    $productNameAttributeId = $this->_attrRepoInt->get('catalog_product', 'name');
    $storeid = $this->_storeMan->getStore();
    // join product entity varchar where attributeid = $productNameAttributeId
    // and entity_id to product_id of my table, where store id = $storeid
    return $this;
}

Then in the Grid/Collection I can just call this, I have done this fine with other joins but they did not require access to other classes in the Collection:

    protected function _initSelect()
{
    parent::_initSelect();
    $this->joinProductNames();
    return $this;
}

So my question is how do I get those 2 classes to load? Or how can I get access to product name via product id some other way? My preference is to join in the grid so that it has better performance rather than making a column render.

** Edit **
Just a note, I can get this working by manually instantiating the object manager and getting the ids I need, but I'd prefer if I can do it the way that I am supposed to be doing it by using the DI in the constructor. Here is the "hack" method:

    /**
 * Join Products table to get product names
 *
 * @return $this
 */
public function joinProductNames()
{
    $attr = $this->getAttributeIdofProductName();
    $storeid = $this->getStoreId();
    $this->getSelect()
        ->joinLeft(
        ['catalog_product_entity_varchar' => $this->getTable('catalog_product_entity_varchar')],
        "main_table.product_id = catalog_product_entity_varchar.entity_id",
            ["product_name" => "value"])
        ->where(
            "catalog_product_entity_varchar.store_id = " . $storeid)
        ->where(
            "catalog_product_entity_varchar.attribute_id = " . $attr
    );
    return $this;
}

/**
 * Get EAV id of the product name attribute
 *
 * @return mixed
 */

private function getAttributeIdofProductName(){
    $om = \Magento\Framework\App\ObjectManager::getInstance();
    /** @var \Magento\Store\Model\StoreManagerInterface $manager */
    $attr = $om->get('\Magento\Eav\Api\AttributeRepositoryInterface');
    $productNameAttributeId = $attr->get('catalog_product', 'name')->getId();
    return $productNameAttributeId;
}

/**
 * Get store id of current store id of admin
 *
 * @return int
 */

private function getStoreId()
{
    $om = \Magento\Framework\App\ObjectManager::getInstance();
    /** @var \Magento\Store\Model\StoreManagerInterface $manager */
    $manager = $om->get('Magento\Store\Model\StoreManagerInterface');
    $storeid = $manager->getStore()->getId();
    if($storeid == 1){
        return 0;
    } else {
        return $storeid;
    }
}

Best Answer

You have logical error in you code. Required params should not be after optional. DI ignore this parameters. Change the order of params from

\Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
\Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null,
\Magento\Eav\Api\AttributeRepositoryInterface $attrRepoInt, // ** will not load
\Magento\Store\Model\StoreManagerInterface $storeMan // ** will not load 

to

\Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Eav\Api\AttributeRepositoryInterface $attrRepoInt, // ** now, will load
\Magento\Store\Model\StoreManagerInterface $storeMan // ** now, will load
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
\Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null,

and it resolve your problem

Related Topic