3

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;
    }
}
2

1 Answer 1

3

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

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.