Following our last example on how to extend the product form with a custom text input, the next step to follow is to save the custom value of it everything the form is saved; when the product form is extended by using attributes created manually, Magento will deal with all saving process, but since we are extending the product form programmatically we need to save the value ourselves.

For this let’s suppose we already created the database tables and a whole model repository/interface structure for saving and retrieving data to retrieve/save data into it (these topics will not be covered in this article).

The big mistake!!!

The most common mistake when saving a custom field in the product form is to implement an observer for catalog_product_save_before or catalog_product_save_after or a plugin to intercept the saving method of the product repository. 

Unfortunately, by doing any of these methods there are high chances of accidentally creating an infinite loop, especially if you need to save any data to the product model itself; because saving the product will trigger another save event, and that event will be continually intercepted by the observer or plugin that will save again… and will keep doing this over and over again.

For avoiding an infinite loop, it is much safer to implement an aroundPlugin to the controller Magento\Catalog\Controller\Adminhtml\Product\Save, because by intercepting the controller we can have access to the form’s data before being saved, not having to perform a “double save” action compared to other methods.

Declare the plugin

Add the plugin declaration in your CustomModule/Vendor/etc/adminhtml/di.xml

<type 

   name=”Magento\Catalog\Controller\Adminhtml\Product\Save”>

      <plugin 

         name=”check_direct_qty_plugin”

         type=”AstralWeb\Quantity\Plugin\SaveProductPlugin”

         sortOrder=”50″ />

</type>

Name your plugin with any name you want and write your plugin file inside the Plugin folder. In this particular case, the filename is SaveProductPlugin.

In the file, we will inject any class we require and declare a beforeDispatch or an aroundDispatch function for having access to the request parameters:

public function aroundDispatch(Save $subject, $proceed, $request)

{

   $params = $request->getParams();

At this point, we should go back to our previous field definition to check for the scope defined for our custom input text.

<argument name=”data” xsi:type=”array”>

   <item name=”config” xsi:type=”array”>

      <item name=”label” xsi:type=”string” translate=”true”>

         Product Qty

      </item>

      <item name=”dataScope” xsi:type=”string”>qty</item>

      <item name=”sortOrder” xsi:type=”number”>500</item>

      <item name=”componentType” xsi:type=”string”>field</item>

      <item name=”dataType” xsi:type=”string”>text</item>

      <item name=”formElement” xsi:type=”string”>input</item>

      <item name=”additionalClasses” xsi:type=”string”>qty</item>

   </item>

</argument>

Since we declare qty as our dataScope it means we must access the value as follows:

public function aroundDispatch(Save $subject, $proceed, $request)

{

   $params = $request->getParams();

   echo $params[‘qty’];

// All your logic for saving the value into the database

return $proceed($request);

}

Applying the changes

After developing the code, execute the followings commands for applying our changes to the environment:

bin/magento setup:upgrade;

bin/magento setup:di:compile;

bin/magento setup:static-content:deploy en_US es_MX;

bin/magento index:reindex;

bin/magento cache:flush;

bin/magento cache:clean;

After executing the above commands, edit any product and enter any integer in the custom text input and save it; you will see immediately that the custom value is saved into the database.

What’s next?

After making sure our custom value is being saved into our database we can start to retrieve it and display it every time the product form is being open. The next article will cover the steps for loading the data back after saving it successfully.