Magento 2 Plugin Limitations

Limitations

Plugins can not be used on following:

  • Final methods
  • Final classes
  • Non-public methods
  • Class methods (such as static methods)
  • __construct
  • Virtual types
  • Objects that are instantiated before Magento\Framework\Interception is bootstrapped

Magento 2 Custom Router and the Dreaded 100 matches

public function match (\Magento\Framework\App\RequestInterface $request)
{
    if (strpos($request->getPathInfo(), 'test') === false) return;
    $request->setModuleName(‘MyCompany_MyModule’)
       ->setControllerName('test')->setActionName('test');

    return $this->actionFactory->create(
        \Magento\Framework\App\Action\Forward::class, ['request' => $request]
    );
}

https://magento.stackexchange.com/questions/135532/magento-2-ce-front-controller-reached-100-router-match-iterations-issue

Magento 1 Admin Form Fields

All the different type of form fields available in magento are located in folder lib\Varien\Data\Form\Element

Text Field

Here is how to add a text field to an admin form, with a list of all the options

$fieldset->addField('title', 'text', array(
          'label'     => Mage::helper('form')->__('Title3'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "alert('on click');",
		  'onchange' => "alert('on change');",
		  'style'   => "border:10px",
		  'value'  => 'hello !!',
		  'disabled' => false,
		  'readonly' => true,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Time
$fieldset->addField('time', 'time', array(
          'label'     => Mage::helper('form')->__('Time'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '12,04,15',
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
TextArea
$fieldset->addField('textarea', 'textarea', array(
          'label'     => Mage::helper('form')->__('TextArea'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '<b><b/>',
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Submit Button
$fieldset->addField('submit', 'submit', array(
          'label'     => Mage::helper('form')->__('Submit'),
          'required'  => true,
		  'value'  => 'Submit',
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
DropDown
$fieldset->addField('select', 'select', array(
          'label'     => Mage::helper('form')->__('Select'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '1',
		  'values' => array('-1'=>'Please Select..','1' => 'Option1','2' => 'Option2', '3' => 'Option3'),
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));

Here is another version of the drop down

$fieldset->addField('select2', 'select', array(
          'label'     => Mage::helper('form')->__('Select Type2'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '4',
		  'values' => array(
		  						'-1'=>'Please Select..',
		  						'1' => array( 
												'value'=> array(array('value'=>'2' , 'label' => 'Option2') , array('value'=>'3' , 'label' =>'Option3') ),
												'label' => 'Size'	 
										   ),
								'2' => array( 
												'value'=> array(array('value'=>'4' , 'label' => 'Option4') , array('value'=>'5' , 'label' =>'Option5') ),
												'label' => 'Color'	 
										   ),										   
							     
						   ),
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Radio Button
$fieldset->addField('radio', 'radio', array(
          'label'     => Mage::helper('form')->__('Radio'),
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '1',
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
$fieldset->addField('radio2', 'radios', array(
          'label'     => Mage::helper('form')->__('Radios'),
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '2',
		  'values' => array(
		  					array('value'=>'1','label'=>'Radio1'),
		  					array('value'=>'2','label'=>'Radio2'),
		  					array('value'=>'3','label'=>'Radio3'),
		  			   ),
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Password Field
$fieldset->addField('password', 'password', array(
          'label'     => Mage::helper('form')->__('Password'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'style'   => "",
		  'value'  => 'hello !!',
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
$fieldset->addField('obscure', 'obscure', array(
          'label'     => Mage::helper('form')->__('Obscure'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'obscure',
		  'onclick' => "",
		  'onchange' => "",
		  'style'   => "",
		  'value'  => '123456789',
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Note
$fieldset->addField('note', 'note', array(
          'text'     => Mage::helper('form')->__('Text Text'),
		));
Multiselect
$fieldset->addField('multiselect2', 'multiselect', array(
          'label'     => Mage::helper('form')->__('Select Type2'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "return false;",
		  'onchange' => "return false;",
		  'value'  => '4',
		  'values' => array(
		  						'-1'=> array( 'label' => 'Please Select..', 'value' => '-1'),
		  						'1' => array( 
												'value'=> array(array('value'=>'2' , 'label' => 'Option2') , array('value'=>'3' , 'label' =>'Option3') ),
												'label' => 'Size'	 
										   ),
								'2' => array( 
												'value'=> array(array('value'=>'4' , 'label' => 'Option4') , array('value'=>'5' , 'label' =>'Option5') ),
												'label' => 'Color'	 
										   ),										   
							     
						   ),
		  'disabled' => false,
		  'readonly' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
		
Multiline
$fieldset->addField('multiline', 'multiline', array(
          'label'     => Mage::helper('form')->__('Multi Line'),
          'class'     => 'required-entry',
          'required'  => true,
          'name'      => 'title',
		  'onclick' => "",
		  'onchange' => "",
		  'style'   => "border:10px",
		  'value'  => 'hello !!',
		  'disabled' => false,
		  'readonly' => true,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Link
$fieldset->addField('link', 'link', array(
          'label'     => Mage::helper('form')->__('Link'),
		  'style'   => "",
		  'href' => 'www.excellencemagentoblog.com',
		  'value'  => 'Magento Blog',
		  'after_element_html' => ''
		));
Label
$fieldset->addField('label', 'label', array(
          'value'     => Mage::helper('form')->__('Label Text'),
		));
Image Upload
$fieldset->addField('image', 'image', array(
          'value'     => 'http://www.excellencemagentoblog.com/wp-content/themes/excelltheme/images/logo.png',
		));
File Upload
$fieldset->addField('file', 'file', array(
          'label'     => Mage::helper('form')->__('Upload'),
		  'value'  => 'Uplaod',
		  'disabled' => false,
		  'readonly' => true,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
Date
$fieldset->addField('date', 'date', array(
          'label'     => Mage::helper('form')->__('Date'),
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1,
		  'image' => $this->getSkinUrl('images/grid-cal.gif'),
	      'format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) 
		));
Checkbox
$fieldset->addField('checkbox', 'checkbox', array(
          'label'     => Mage::helper('form')->__('Checkbox'),
          'name'      => 'Checkbox',
		  'checked' => false,
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '1',
		  'disabled' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));
$fieldset->addField('checkboxes', 'checkboxes', array(
          'label'     => Mage::helper('form')->__('Checkboxs'),
          'name'      => 'Checkbox',
		  'values' => array(
		  					array('value'=>'1','label'=>'Checkbox1'),
		  					array('value'=>'2','label'=>'Checkbox2'),
		  					array('value'=>'3','label'=>'Checkbox3'),
		  			   ),
		  'onclick' => "",
		  'onchange' => "",
		  'value'  => '1',
		  'disabled' => false,
		  'after_element_html' => '<small>Comments</small>',
		  'tabindex' => 1
		));

Magento 2.3 Declarative Schema

In an effort to simplify the Magento installation and upgrade process, 2.3 introduces declarative schema.

With the new declarative schema approach allows,  developers are no longer forced to write scripts for each new version of a module. Using declarative schema, developers declare the final desired state of the database, and the system adjusts to it automatically, without performing redundant operations. In addition, this approach allows data to be easily deleted when a module is uninstalled.

There are two parts to using declarative schema: the db_schema.xml file and the bin/magento command to register it.

Once you use declarative schema in a module, you cannot use setup/upgrade scripts again. In the future, upgrade scripts will be phased out in favor of declarative schema.

The following example, extracted from the Catalog/etc/db_schema.xml file, defines the catalog_product_entity_datetime table:

<table name="catalog_product_entity_datetime" resource="default" engine="innodb"
           comment="Catalog Product Datetime Attribute Backend Table">
        <column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
        <column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false"default="0" comment="Attribute ID"/>
        <column xsi:type="smallint" name="store_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Store ID"/>
        <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0"/>
        <column xsi:type="datetime" name="value" on_update="false" nullable="true" comment="Value"/>
        <constraint xsi:type="primary" name="PRIMARY">
            <column name="value_id"/>
        </constraint>
</table>

https://magento-devdocs.github.io/devdocs-for-tests/guides/v2.3/extension-dev-guide/declarative-schema/db-schema.html

Magento 2 Knockout JS in a Nutshell

We have defined a module with a simple module.xml and a registration.php file,

to call upon the regular flow of M2 merged XML layouts, to define a Block class that feeds data into a PHTML template,

which is then outputting a JSON configuration array that was inserted into the Block class using an XML argument-array,

and which is then used to initialize a custom AMD-style JS component through the Magento_Ui/js/core/app component,

which connects our require JS component to our KnockoutJS component.

Then, our JS component injects the customer-data component to collect a bit of information about the customer, which is fetched through a kind of local-storage-cached-AJAX-call to the backend,

which is configured through a DI type that injects an array of section sources into a backend class,

that fetches data from various sources, including our own, to then send back a bundled response, if possible, to the JS component, with the major feature being JavaScript AJAX lazy loading.

Namespace

/Module

/Block

Block.php

/etc

module.xml

/view

/frontend

/layouts

somelayout_file.xml

/templates

template.phtml

registration.php

Add Quantity to Product Widget Grid in Category Edit in Magento 2

Event/Observer

Event: backend_block_widget_grid_prepare_grid_before

Create Module

Namespace\Module\registration.php
Namespace\Module\composer.json
Namespace\Module\etc\module.xml
Namespace\Module\etc\adminhtml\events.xml
Namespace\Module\Model\Observer\BackendBlockWidgetGridPrepareGrid.php

events.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="backend_block_widget_grid_prepare_grid_before">
        <observer name="category_product_picker_grid"
                  instance="Namespace\Module\Model\Observer\BackendBlockWidgetGridPrepareGrid"
        />
    </event>
</config>

BackendBlockWidgetGridPrepareGrid.php

namespace Namespace\Module\Model\Observer;

use Magento\Framework\Event\ObserverInterface;

class BackendBlockWidgetGridPrepareGrid implements ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $grid = $observer->getEvent()->getGrid();
        $grid->addColumn(
            'qty',
            [
                'header' => __('Quantity'),
                'type' => 'number',
                'index' => 'stock'
            ]
        );
        return $this;
    }
}

Magento 1 Front controller reached 100 router match iterations

a:5:{i:0;s:52:"Front controller reached 100 router match iterations";i:1;s:499:"#0 /www/sites/*/app/code/core/Mage/Core/Controller/Varien/Front.php(183): Mage::throwException('Front controlle...')

#1 /www/sites/*/app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()

#2 /www/sites/*/app/Mage.php(683): Mage_Core_Model_App->run(Array)

#3 /www/sites/*/index.php(90): Mage::run('gloso_public', 'website')

#4 {main}";s:3:"url";s:17:"/admin";s:11:"script_name";s:16:"/index.php";s:4:"skin";s:17:"default";}

https://github.com/convenient/magento-ce-ee-config-corruption-bug#the-fix