3

I am developing a custom module in Magento 2. I would like to add to the editing form a multiselect to allow users to select the store view. In Magento 1.9 it is done in this way:

$fieldset->addField('store_id', 'multiselect', array(
        'name' => 'stores[]',
        'label' => Mage::helper('myhelper')->__('Store View'),
        'title' => Mage::helper('myhelper')->__('Store View'),
        'required' => true,
        'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true),
    ));

How can this be done in Magento 2?

3 Answers 3

12

You should inject class Magento\Store\Model\System\Store in the constructor and declare a global variable.

E.g:

public function __construct(
   //...,
   Magento\Store\Model\System\Store $systemStore
) {
   //...
  $this->_systemStore = $systemStore;
}

protected function _prepareForm()
{
    //...
    $fieldset->addField(
       'store_ids',
       'multiselect',
       [
         'name'     => 'store_ids[]',
         'label'    => __('Store Views'),
         'title'    => __('Store Views'),
         'required' => true,
         'values'   => $this->_systemStore->getStoreValuesForForm(false, true),
       ]
    );
}

I hope it was helpful.

8
  • Hi bill thanks for your code. I copy this code in my module it's display properly in form but store id not stored in database after save form. it's store null value in database. Commented Feb 25, 2017 at 7:25
  • Hi Bill, Thanks a lot for this piece of code. It works like a charm. The store id is not stored in DB. Any Idea to achieve this ? Thx in advance
    – Flow
    Commented Apr 21, 2017 at 5:37
  • How to store store values in custom table in database? Commented Jun 8, 2017 at 6:10
  • 1
    You should using _afterSave() function on ResourceModel to save this value
    – LinoPham
    Commented Jun 8, 2017 at 8:18
  • 1
    Can you please add _afterSave() function code for save store_id in my custom table? Commented Jun 8, 2017 at 12:57
2

For save why not to just implode the array

 $data['store_ids'] = implode(',', $this->getRequest()->getParam('store_ids'));
1
  • How do you do this?> Commented Dec 9, 2019 at 14:06
1

In addition to adding the field to your form (see Bill's accepted answer), you need logic to save this field to the database. Because it is a compound field (a model might apply to more than one store view) it is good practice to save this to a separate table (normalization principle).

Use a UpgradeSchema to create a table with the _store suffix. This has two columns: item_id and store_id. You might configure indices and/or foreign keys for performance gains but it's not strictly required. I assume you know how to do that so I won't post any code there.

Then in your model you need to add the additional logic for loading and saving to that second table. In my example I have model MyItem with table my_items so I need to create a table my_items_store and add the following functions to my class in Vendor\NameSpace\Model\Resource\MyItem:

/**
 * @param \Magento\Framework\Model\AbstractModel $object
 * @return void
 */
protected function saveStore($object)
{
    $condition = $this->getConnection()->quoteInto('item_id = ?', $object->getId());
    $this->getConnection()->delete($this->getTable('my_items_store'), $condition);
    foreach ((array)$object->getData('store_ids') as $store) {
        $storeArray = [
            'item_id' => $object->getId(),
            'store_id' => $store,
        ];
        $this->getConnection()->insert(
            $this->getTable('my_items_store'),
            $storeArray
        );
    }
}

/**
 * @param \Magento\Framework\Model\AbstractModel $object
 * @return $this
 */
protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
{
    if (!$object->getIsMassStatus()) {
        $this->saveStore($object);
    }

    return parent::_afterSave($object);
}

/**
 * @param \Magento\Framework\Model\AbstractModel $object
 * @return \Magento\Framework\Model\AbstractModel
 */
public function loadStore(\Magento\Framework\Model\AbstractModel $object)
{
    $select = $this->getConnection()->select()
        ->from($this->getTable('my_items_store'))
        ->where('item_id = ?', $object->getId());

    if ($data = $this->getConnection()->fetchAll($select)) {
        $array = [];
        foreach ($data as $row) {
            $array[] = $row['store_id'];
        }
        $object->setData('store_id', $array);
    }

    return $object;
}

/**
 * @param \Magento\Framework\Model\AbstractModel $object
 * @return $this
 */
protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
{
    if (!$object->getIsMassDelete()) {
        $this->loadStore($object);
    }

    return parent::_afterLoad($object);
}

The function _afterSave() is called automatically when the save() function is called on the Model. The same goes for _afterLoad() when loading the Model. Copy these functions to your model, change the table to the name of your newly created table and you're good to go!

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.