Magento 2 – Fix Collection on Custom Table Problem

collection;magento2modelPHP

I created my custom table on magento, with the InstallSchema and InstallData and It works fine, then I created my Model class, initially it seemed to work, because I used the collection in one Block and I was able to get the information from my table.

Now I'm writing another block where I need the same information, but with different filter. But when I get dump the string of my collection, get It with the filter of the first block and the second.

my Db table name is: <vendor>_macrocategoria_option and Its key is: option_id

here my model: <Vendor>\<Module>\Model\Option.php

<?php 
 namespace <Vendor>\<Module>\Model; 

 class Option extends \Magento\Framework\Model\AbstractModel {

 const OPTION_ID = 'option_id';

/**
 * Prefix of model events names
 *
 * @var string
 */
protected $_eventPrefix = 'settings_option'; // parent value is 'core_abstract'

/**
 * Name of the event object
 *
 * @var string
 */
protected $_eventObject = 'macrocategoria_option'; // parent value is 'object'

/**
 * Name of object id field
 *
 * @var string
 */
protected $_idFieldName = self::OPTION_ID; // parent value is 'id'

/**
 * Initialize resource model
 *
 * @return void
 */
protected function _construct()
{
    $this->_init('<Vendor>\<Module>\Model\ResourceModel\Option');
}}

here my resourceModel: <Vendor>\<Module>\Model\ResourceModel\Option.php

<?php 
 namespace <Vendor>\<Module>\Model\ResourceModel; 

 class Option extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb {

/**
 * Resource initialization
 *
 * @return void
 */
protected function _construct()
{
    // Table Name and Primary Key column
    $this->_init('<vendor>_macrocategoria_option', 'option_id');
}}

finally, here my collection: <Vendor>\<Module>\Model\ResourceModel\Option\Collection.php

<?php 
 namespace <Vendor>\<Module>\Model\ResourceModel\Option;

 class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection {
/**
 * Define resource model
 *
 * @return void
 */
protected function _construct()
{
    $this->_init(
        '<Vendor>\<Module>\Model\Option',
        '<Vendor>\<Module>\Model\ResourceModel\Option'
    );
}}

Edit

This is the first block where I use my collection: <Vendor>\<module1>\Block\Macrocategorie.php

<?php 
 namespace <Vendor>\<Module1>\Block; 

 use Magento\Framework\View\Element\Template; 

 class Macrocategorie extends \Magento\Framework\View\Element\Template {

const MACRO_TYPE_CODE = 'macrocategoria';

/**
 * @var \<Vendor>\<Module>\Model\ResourceModel\Option\Collection
 */
protected $_macroOptionCollection;

/**
 * Macrocategorie constructor.
 * @param Template\Context $context
 * @param \<Vendor>\<Module>\Model\ResourceModel\Option\Collection $option
 * @param array $data
 */
public function __construct(
    Template\Context $context,
    \<Vendor>\<Module>\Model\ResourceModel\Option\Collection $option,
    array $data = []
)
{
    $this->_macroOptionCollection = $option;
    parent::__construct($context, $data);
}

public function getMacrocategorie()
{
    $macrocategorie = array();
    $options = $this->_macroOptionCollection
        ->addFieldToFilter('type_code', $this::MACRO_TYPE_CODE)
        ->setOrder('sort_order', 'ASC')
        ->load();

    /* do something with my $options */

    return $macrocategorie;
}}

This is the second: <Vendor>\<module2>\Block\ProductList\Evidenza.php

<?php 
 namespace <Vendor>\<Module2>\Block\ProductList; 

 class Evidenza extends \<Vendor>\<Module2>\Block\ProductAbstract {

const EVIDENZA = 'evidenza';

/**
 * @var \<Vendor>\<Module>\Model\ResourceModel\Option\Collection
 */
protected $_settingCollection;

/**
 * Evidenza constructor.
 * @param \Magento\Catalog\Block\Product\Context $context
 * @param \Magento\Framework\Pricing\Helper\Data $priceHelper
 * @param \Magento\Catalog\Model\CategoryFactory $modelCategory
 * @param \<Vendor>\<Module>\Model\ResourceModel\Option\Collection $settingsCollection
 * @param array $data
 */
public function __construct(
    \Magento\Catalog\Block\Product\Context $context,
    \Magento\Framework\Pricing\Helper\Data $priceHelper,
    \Magento\Catalog\Model\CategoryFactory $modelCategory,
    \<Vendor>\<Module>\Model\ResourceModel\Option\Collection $settingsCollection,
    array $data = []
)
{
    parent::__construct(
        $context,
        $priceHelper,
        $modelCategory,
        $data
    );

    $this->_settingCollection = $settingsCollection;
}

/**
 * Metodo che in base alla tipologia di griglia richiesta (type_grid) restituisce la collezione di prodotti
 * specifica
 *
 * @return array|mixed
 */
public function getCollectionProducts()
{
    $productsCollection = null;



    /*
    In this way the filter works fine

    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $settingsCollection = $objectManager->create('\<Vendor>\<Module>\Model\ResourceModel\Option\Collection');

    $options = $settingsCollection
        ->addFieldToFilter('type_code', $this::EVIDENZA)
        ->setOrder('sort_order', 'ASC')
        ->load();*/

    // In this way I get also the filter of the first block

    $options = $this->_settingCollection
        ->addFieldToFilter('type_code', $this::EVIDENZA)
        ->setOrder('sort_order', 'ASC')
        ->load();

    /* Do something with $options */

    return $productsCollection;
}}

Best Answer

Need to add $_idFieldName in the collection

<Vendor>\<Module>\Model\ResourceModel\Option\Collection.php:

protected $_idFieldName = 'option_id';

There are some notes after discussing:

  • Try to use Collection Factory: \<Vendor>\<Module>\Model\ResourceModel\Option\CollectionFact‌​ory.

  • If in production mode: try to clear var/di, var/cache/, var/generation/ folder and run di complie again.

  • In in developer mode: try to clear cache and var/generation.