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

comparing core_config_data

Find core_config_data differences between a production and development db.

SELECT path, value FROM (
SELECT path, value FROM your_dev_db.core_config_data
UNION ALL
SELECT path, value FROM your_prod_db.core_config_data
) tbl
GROUP BY path, value
HAVING count(*) = 1
ORDER BY path


query("select * from core_config_data where path in (
'admin/url/custom',
'admin/url/use_custom',
'carriers/ups/access_license_number',
'carriers/ups/allowed_methods',
'carriers/ups/dest_type',
'carriers/ups/dest_type',
'carriers/ups/negotiated_active',
'carriers/ups/negotiated_active',
'carriers/ups/password',
'carriers/ups/username',
'dev/css/merge_css_files',
'dev/js/merge_files',
'payment/authorizenet/cgi_url',
'payment/authorizenet/cgi_url_td',
'payment/authorizenet/login',
'payment/authorizenet/merchant_email',
'payment/authorizenet/test',
'payment/authorizenet/trans_key',
'payment/cashondelivery/active',
'payment/paypal_direct/cctypes',
'payment/paypal_direct/payment_action',
'payment/paypal_direct/sort_order',
'paypal/general/business_account',
'paypal/wpp/api_password',
'paypal/wpp/api_signature',
'paypal/wpp/api_username',
'paypal/wpp/sandbox_flag',
'shipping/origin/postcode',
'shipping/origin/region_id',
'system/currency/installed',
'web/cookie/cookie_domain',
'web/cookie/cookie_path',
'web/secure/base_js_url',
'web/secure/base_media_url',
'web/secure/base_skin_url',
'web/secure/base_url',
'web/unsecure/base_js_url',
'web/unsecure/base_media_url',
'web/unsecure/base_skin_url',
'web/unsecure/base_url')");

foreach ($result as $row) {
echo "update `core_config_data` set `value` = '" . $row['value'] . "' where `path`='" . $row['path'] . "';" . PHP_EOL;
}
?>

Magento 2 Simple Products and Virtual Products and Hey, There’s No Weight Attribute!

So you’re loving your new Magento 2 store when all of a sudden you realize, your simple products have started turning themselves into virtual products. Magento 2 automagically freely converts simple products to virtual and virtual products to simple based on whether or not the product has a weight.

All you have to do to turn those virtual products back into simple products is provide a value for weight. When you go in to edit the product, though, you may find there is no weight attribute on the screen!

Look in eav_attribute for the weight attribute_code and get its attribute_id (entity_type_id is probably 4). Look in catalog_eav_attribute where attribute_id is the one you just looked up from eav_attribute and set apply_to NULL. Reload product edit page, and you should see weight now

Weight Restored
Weight Restored

Magento 2 Get Paths Programatically

Looking for Mage::getBaseUrl in Magento 2?
Use the DirectoryList class in your constructor to get an instance of DirectoryList.

Magento\Framework\App\Filesystem\DirectoryList $directory_list

For getting your Magento 2 root folder you can use

$this->directory_list->getRoot();

For getting media folder you can use

$this->directory_list->getPath('media');

 

Other possible uses are:

/* Get app folder */
$this->directory_list->getPath('app');
 
/* Get configuration folder */
$this->directory_list->getPath('etc');
 
/* Get libraries or third-party components folder */
$this->directory_list->getPath('lib_internal');
 
/* Get libraries/components that need to be accessible publicly through web-server folder */
$this->directory_list->getPath('lib_web');
 
/* Get public folder */
$this->directory_list->getPath('pub');
 
/* Get static folder */
$this->directory_list->getPath('static');
 
/* Get var folder */
$this->directory_list->getPath('var');
 
/* Get temporary files folder */
$this->directory_list->getPath('tmp');
 
/* Get file system caching directory (if file system caching is used) */
$this->directory_list->getPath('cache');
 
/* Get logs of system messages and errors */
$this->directory_list->getPath('log');
 
/* Get file system session directory (if file system session storage is used) */
$this->directory_list->getPath('session');
 
/* Get directory for Setup application*/
$this->directory_list->getPath('setup');
 
/* Get Dependency injection related file directory */
$this->directory_list->getPath('di');
 
/* Relative directory key for generated code*/
$this->directory_list->getPath('generation');
 
/* Temporary directory for uploading files by end-user */
$this->directory_list->getPath('upload');
 
/* Directory to store composer related files (config, cache etc.) in case if composer runs by Magento Application */
$this->directory_list->getPath('composer_home');
 
/* A suffix for temporary materialization directory where pre-processed files will be written (if necessary) */
$this->directory_list->getPath('view_preprocessed');
 
/* Get template minification dir */
$this->directory_list->getPath('html');
 

Magento Indexers – Programmatically Using Indexers

In some custom modules, you may need to change the index mode from manual to auto or vice versa or you may need to run one of the indexers.

$pCollection
    = Mage::getSingleton('index/indexer')->getProcessesCollection();
foreach ($pCollection as $process) {
    //$process->setMode(Mage_Index_Model_Process::MODE_MANUAL)->save();
    $process->setMode(Mage_Index_Model_Process::MODE_REAL_TIME)->save();
}

$pCollection
    = Mage::getSingleton('index/indexer')->getProcessesCollection();
foreach ($pCollection as $process) {
    $process->reindexEverything();
}

Indexes can be loaded using either the process ID or the process code using the functions:

by ID:

$process = Mage::getSingleton('index/indexer')->getProcessById();

by CODE:

$process = Mage::getSingleton('index/indexer')->getProcessByCode(<process_code>);

 

The process code and ID can be found by checking the table index_process. The Magento provided indexes normally have the following ID and code.

Process Name ID Code
Product Attributes 1 catalog_product_attribute
Product Prices 2 catalog_product_price
Catalog URL Rewrites 3 catalog_url
Product Flat Data 4 catalog_product_flat
Category Flat Data 5 catalog_category_flat
Category Products 6 catalog_category_product
Catalog Search Index 7 catalogsearch_stock
Stock Status 8 cataloginventory_stock
Tag Aggregation Data 9 tag_summary

 

Magento Flush Cache from FTP

->FTP users can use the following command to cleanup Magento caches:

mrm -r ./var/cache ; mkdir ./var/cache

mrm -r ./var/full_page_cache ; mkdir ./var/full_page_cache

Magento Field Validation Class Options

‘validate-no-html-tags’ => ‘HTML tags are not allowed’

‘validate-select’ => ‘Please select an option.’

‘required-entry’ => ‘This is a required field.’

‘validate-number’ => ‘Please enter a valid number in this field.’

‘validate-number-range’ => ‘The value is not within the specified range.’

‘validate-digits’ => ‘Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.’

‘validate-digits-range’ => ‘The value is not within the specified range.’

‘validate-alpha’ => ‘Please use letters only (a-z or A-Z) in this field.’

‘validate-code’ => ‘Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.’

‘validate-alphanum’ => ‘Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.’

‘validate-alphanum-with-spaces’ => ‘Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.’

‘validate-street’ => ‘Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.’

‘validate-phoneStrict’ => ‘Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.’

‘validate-phoneLax’ => ‘Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.’ ‘validate-fax’ => ‘Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.’ ‘validate-date’ => ‘Please enter a valid date.’ ‘validate-date-range’ => ‘The From Date value should be less than or equal to the To Date value.’ ‘validate-email’ => ‘Please enter a valid email address. For example johndoe@domain.com.’ ‘validate-emailSender’ => ‘Please use only visible characters and spaces.’ ‘validate-password’ => ‘Please enter 6 or more characters. Leading or trailing spaces will be ignored.’ ‘validate-admin-password’ => ‘Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.’ ‘validate-both-passwords’ => ‘Please make sure your passwords match.’ ‘validate-url’ => ‘Please enter a valid URL. Protocol is required (http://, https:// or ftp://)’ ‘validate-clean-url’ => ‘Please enter a valid URL. For example http://www.example.com or www.example.com’ ‘validate-identifier’ => ‘Please enter a valid URL Key. For example “example-page”, “example-page.html” or “anotherlevel/example-page”.’ ‘validate-xml-identifier’ => ‘Please enter a valid XML-identifier. For example something_1, block5, id-4.’ ‘validate-ssn’ => ‘Please enter a valid social security number. For example 123-45-6789.’ ‘validate-zip’ => ‘Please enter a valid zip code. For example 90602 or 90602-1234.’ ‘validate-zip-international’ => ‘Please enter a valid zip code.’ ‘validate-date-au’ => ‘Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.’ ‘validate-currency-dollar’ => ‘Please enter a valid $ amount. For example $100.00.’ ‘validate-one-required’ => ‘Please select one of the above options.’ ‘validate-one-required-by-name’ => ‘Please select one of the options.’ ‘validate-not-negative-number’ => ‘Please enter a number 0 or greater in this field.’ ‘validate-zero-or-greater’ => ‘Please enter a number 0 or greater in this field.’ ‘validate-greater-than-zero’ => ‘Please enter a number greater than 0 in this field.’ ‘validate-state’ => ‘Please select State/Province.’ ‘validate-new-password’ => ‘Please enter 6 or more characters. Leading or trailing spaces will be ignored.’ ‘validate-cc-number’ => ‘Please enter a valid credit card number.’ ‘validate-cc-type’ => ‘Credit card number does not match credit card type.’ ‘validate-cc-type-select’ => ‘Card type does not match credit card number.’ ‘validate-cc-exp’ => ‘Incorrect credit card expiration date.’ ‘validate-cc-cvn’ => ‘Please enter a valid credit card verification number.’ ‘validate-ajax’ => ‘validate-data’ => ‘Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.’ ‘validate-css-length’ => ‘Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.’ ‘validate-length’ => ‘Text length does not satisfy specified text range.’ ‘validate-percents’ => ‘Please enter a number lower than 100.’ ‘validate-cc-ukss’ => ‘Please enter issue number or start date for switch/solo card type.’