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