Aleksandar Krstic

Personal Blog

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

CSS – How to fix the issue with fixed background on scroll in iOS

Your client want to have a fixed background when user scroll down? First thought – piece of cake, and really it is if you disregard the fact that users with iPhone or iPad like to scroll also.

This piece of code will work for every device except ones that have iOS (iPhone, iPad)

body {
    background-image: url("PATH-TO-YOUR-IMAGE");
    overflow-x: hidden;
    background-attachment: fixed;
    position: relative;
    -webkit-background-size: cover;
    -moz-background-size: cover;
    background-size: cover;
    width: 100%;
    height: 100%;
}

Why is that the case here? Per my understanding, Apple disabled position: fixed or background-attachment: fixed style for body element.

So what to do?

1. Open and close div inside of body element

<body>
<div class="ios-fixed-bg"></div>
....
</body>

2. Apply the following style to class ios-fixed-bg

.ios-fixed-bg {
	background-image: url("PATH-TO-YOUR-IMAGE");
	height: 100%;
	width: 100%;
	position: fixed;
	background-position: center;
	background-repeat: no-repeat;
	-webkit-background-size: cover;
        -moz-background-size: cover;
        background-size: cover;
	z-index: -1;
}

Coded UI – Finding Controls – Best Practices

In one of the previous posts I mentioned the ability to use parent-child relations in order to find controls, and in this article I’ll share my experience and what I find as best practice for finding controls.

  1. Always look for ID or Friendly Name. Everythig else try to avoid, especially Tag Instance.
  2. In case that element doesn’t have one of these two, find parent that have.
  3. If both elements – child and parent doesn’t have any of these two, find parent that does

Why is finding ID or Friendly Name important? Simply, ID should be always unique, and Friendly Name is usually unique at least on current page.

Example:

<div id=”ihaveid”>
	<div> <!-- child1 – first child of div with id -->
		<div> <!-- child2 – first child of child1 -->
			<span>This is what I want to find</span> <!-- child3 – first child of child2 -->
		</div>
	</div>
</div>

So, logic here is to find child inside of child until you get where you want to be.

public HtmlDiv FindDivById(UITestControl parent, string id)
        {
            var parentdiv= new HtmlDiv(parent);
            parentdiv.SearchProperties.Add(HtmlDiv.PropertyNames.Id, id);
            return parentdiv;
        }
		
var parent = FindListById(browser, "ihaveid");
var child1 = parent.GetChildren()[0];  // 0 is 1st child, 1 is 2nd child, ….
var child2 = child1.GetChildren()[0]; 
var child3 = child3.GetChildren()[0];
Mouse.Click(child3);    // this is in case that you want to click on it, but logic is same for any other operation

As you see, logic is very simple. Find nearest parent element that have unique control(s) and search for child elements inside of it.

In my example elements used are div and span, but really you can use it in every combination with lists, paragraphs, …