Magento 2 – Cookies with JavaScript

This article is basically follow up on previous one.

There I talked about popup/sliding panel handling, but if you want to improve that with cookies usage (for example, to auto-load popup just once per session or similar …) here you can find some useful tips.

In Magento 2 you can achieve that with PHP or JavaScript (jQuery, mage/cookies, js-cookie, …)

From what I have experienced, the best way is with the js-cookie plugin (inheritor of jQuery Cookies which is “retired” from 2015).

Why not PHP?
PHP approach cannot be implemented in custom block from Magento backend, and JavaScript can through require.js.

Why not jQuery Cookies plugin?
As I mentioned, it’s retired from 2015, and people who worked on it continued the job on js-cookie plugin. Beside that, cookie retrieving not working anymore (at least for me).

So which one?
That plugin can be found here – https://github.com/js-cookie/js-cookie

Only file that you need is – https://github.com/js-cookie/js-cookie/blob/master/src/js.cookie.js

So, steps for the implementation are:

1. Place js.cookie.js in \lib\web
2. Run Static Content Deploy command – php bin/magento setup:static-content:deploy
3. Go to place where you want to use js-cookie and call it.

    require(
        [
            'jquery',
            'js.cookie'
        ],
        function($, Cookies) { …. }

Usage:
Set cookie – Cookies.set(‘name’, ‘value’, { expires: 30 }); // expires in 30 days
Get cookie – Cookies.get(‘name’); //returns value
Remove cookie – Cookies.remove(‘name’);

Complete documentation can be found here
https://github.com/js-cookie/js-cookie

Updated code from the previous article now looks:

<script type="text/javascript">
    require(
        [
            'jquery',
            'Magento_Ui/js/modal/modal',
            'js.cookie'
        ],
        function($, modal, Cookie){
            var options = {
                type: 'popup', // there is also a slide type. By default sliding from the right.
                responsive: true,
                innerScroll: true,
                buttons: [{
                    text: $.mage.__('Close'),
                    class: '',
                    click: function () {
                        this.closeModal();
                    }
                }]
            };
 
            var popup = modal(options, $('#popup-modal'));
             
            //Popup appears on winodow load only once in session
            $( document ).ready(function() {
                    var cookieGet = Cookies.getJSON('amishown');
                    if (cookieGet === null || cookieGet === undefined){
                    $("#popup-modal").modal("openModal");
	            var cookieSet = Cookies.set('amishown', 'shown');
                    } 
             });
        }
    );
</script>

Magento 2 – Popup/slide modal handling

Magento 2 offers very easy way to use popup or sliding panels.

It can be achieved with the following piece of jQuery code anywhere you want (blocks, pages, templates, …).

<script type="text/javascript">
	require(
		[
			'jquery',
			'Magento_Ui/js/modal/modal'
		],
		function($, modal){
			var options = {
				type: 'popup', // there is also a slide type. By default sliding from the right.
				responsive: true,
				innerScroll: true,
				buttons: [{
					text: $.mage.__('Close'),
					class: '',
					click: function () {
						this.closeModal();
					}
				}]
			};

			var popup = modal(options, $('#popup-modal'));
			
			//Popup appears on click on specific emelent with id=click-me			
			$("#click-me").on('click',function(){ 
				$("#popup-modal").modal("openModal");
			});
			
			//Popup appears on winodow load
			$('#popup-modal').modal('openModal');
		}
	);
</script>

Also, you will need some html.

<!-- Link which will trigger popup on click. -->
<a href="#" id="click-me">Click me</a>

<!-- Popup content. -->
<div id="popup-modal">Here goes content modal</div>

As you can it is very easy to handle events (click, on window load, hover, …).

There are 2 types of modals in magento – Popup and Sliding Panel.

More about modal options you can find in official Magento documentation.

Magento 2 – Bulk update product position in category

Magento 2 offers manual way to update position of product in category. This is okay, but in case when you have 5000 products, it’s not that easy to re-order them one by one.

Also, there is a premium tool called “Store Manager for Magento”, and it’s very good, but if you don’t want to spend money on it, this is what I suggest:

*This presumes that you have csv file with sku and position columns ready.

1. Create table temp1 with the following query

CREATE TABLE temp1
SELECT a.category_id, a.product_id, a.position, b.sku
FROM catalog_category_product AS a, catalog_product_entity AS b
WHERE a.product_id = b.entity_id

2. Create table temp2 with 2 columns sku and position (they need to matach structure of same fields in temp1 table)

3. Import you csv file to temp2 table via phpMyAdmin.

4. Execute the following query in order to update temp1 from temp2

UPDATE temp1 t1 
INNER JOIN temp2 t2 
ON t1.sku = t2.sku 
SET t1.position = t2.position

5. Execute the following query in order to update catalog_category_product from temp1

UPDATE catalog_category_product t1 
INNER JOIN temp1 t2 
ON t1.product_id = t2.product_id 
AND t1.category_id = t2.category_id 
SET t1.position = t2.position

IMPORTANT: This will update position of product in all categories in which that product exist.

Magento – Readiness Check shows non-existing error during the installation of Magento extension.

During the extension installation (via Component Manager in Magento backend) I got some weird message in Readiness Check step (PHP Settings section).

“Your current PHP memory limit is 2048M. Magento 2 requires it to be set to 768M or more. As a user with root privileges, edit your php.ini file to increase memory_limit. (The command php –ini tells you where it is located.) After that, restart your web server and try again.”

So, if my memory limit in php.ini is set to 2048MB, how is that less than 768MB? (and yes, I double checked php.ini on correct location).

Here looks like that issue is not related with memory limit at all, anyway until I find out what is actual problem here this is the workaround if you want to continue with extension installation process.

      Locate file PATH-TO-YOUR-MAGENTO-SITE\setup\src\Magento\Setup\Model\PhpReadinessCheck.php
      Update error variable to false in the checkMemoryLimit function (line 201)
if (
            $currentMemoryInteger > 0
            && $this->dataSize->convertSizeToBytes($currentMemoryLimit)
            < $this->dataSize->convertSizeToBytes($minimumRequiredMemoryLimit)
        ) {
	    //$error = true;
            $error = false;
            $message = sprintf(
                'Your current PHP memory limit is %s.
                 Magento 2 requires it to be set to %s or more.
                 As a user with root privileges, edit your php.ini file to increase memory_limit. 
                 (The command php --ini tells you where it is located.) 
                 After that, restart your web server and try again.',
                $currentMemoryLimit,
                $minimumRequiredMemoryLimit
            );
        }

As you can see, logic for displaying error was correct, but for some reason error gets displayed, and process cannot be continued.

This is just (not so clean) workaround, so if some of readers of this post find real solution, please send the feedback.

Speed up Magento on localhost

Some of you experienced for sure how Magento can be slow on localhost (either you use XAMPP, WAMPP or whatever).

There are a few things that can be done in order to speed up Magento on localhost:

1. Increase memory in php.ini and .htaccess file

Php.ini
memory_limit=2048M

Main Magento .htaccess
php_value memory_limit 2048M

2. Enable Cache
Go to System > Cache Management in Magento backend and enable cache for everything listed

3. Static content deploy
Run the following command in terminal (make sure to navigate to Magento site folder first)
php bin/magento setup:static-content:deploy