I am using Magento 2.3.0

I have migrated products from Magento 1 to Magento 2. I can see related products in product detail page in the front end and it is proper and also I can find related products entry in the database as well but when I checked related products in admin I found that there are some related products missing in some of the products

For Ex. When I checked one product in the front end. I saw three related products there as well as in the database but I can find only 2 products in admin there is one product missing in admin.

I checked two tables in database for related products: "catalog_product_link" and "catalog_product_link_attribute_int".

I have found some values in the "value" column in "catalog_product_link_attribute_int" table which represents the position of the related products in admin and in front end but I found value 0 in "value" column of this table for some of the products and when I checked these products I found that only those products which do have only 0 in "value" column in "catalog_product_link_attribute_int" table are missing related products in admin.

So, How can I solve this issue?

Check my below question as well:

How to override product model files in Magento 2?

I have created a new module to solve the related product issue which I mentioned in this question but I got an error.

有帮助吗?

解决方案

Why it happens

This happens when there are inconsistent positions for the related products. This might happen after a migration from magento 1. It was the case for me also.

The problem is cause by the method Magento\Catalog\Model\ProductLink\CollectionProvider::getCollection().
That's the one responsible for retrieving the products.

The part that does not behave as expected is this:

    foreach ($output as $item) {
        $itemPosition = $item['position'];
        if (!isset($sorterItems[$itemPosition])) {
            $sorterItems[$itemPosition] = $item;
        } else {
            $newPosition = $itemPosition + 1;
            $sorterItems[$newPosition] = $item;
        }
    }

Let's take 2 cases.
THe one that works:

Let's say

$output = [
     ['position' => 0],
     ['position' => 2],
     ['position' => 1],

];

(I ignored the other values for the related items as they are not important).
After running the code above this results in

Array
(
    [0] => Array
        (
            [position] => 0
        )

    [2] => Array
        (
            [position] => 2
        )

    [1] => Array
        (
            [position] => 1
        )

)

which is later sorted by the ksort function.
So 3 items on input, 3 on output. So far so good.

But let's take this case:

$output = [
    ['position' => 0], // or null
    ['position' => 1],
    ['position' => 0], // or null
];

The same piece of code returns:

Array
(
    [0] => Array
        (
            [position] => 0
        )

    [1] => Array
        (
            [position] => 0
        )

)

So 3 items in, 2 out.

Solution

I solve this by rewriting the method mentioned above and ensuring there are no position clashes.

To override it, add this in the di.xml file in one of your custom modules

<preference for="Magento\Catalog\Model\ProductLink\CollectionProvider" type="[Vendor]\[Module]\Model\ProductLink\CollectionProvider" />

Then create the class [Vendor]\[Module]\Model\ProductLink\CollectionProvider in the file [Vendor]/[Module]/Model/ProductLink/CollectionProvider.php

The class should look like this:

<?php
namespace [Vendor]\[Module]\Model\ProductLink;

use Magento\Framework\Exception\NoSuchEntityException;

class CollectionProvider extends \Magento\Catalog\Model\ProductLink\CollectionProvider
{
    /**
     * Get product collection by link type
     *
     * @param \Magento\Catalog\Model\Product $product
     * @param string $type
     * @return array
     * @throws NoSuchEntityException
     */
    public function getCollection(\Magento\Catalog\Model\Product $product, $type)
    {
        if (!isset($this->providers[$type])) {
            throw new NoSuchEntityException(__('Collection provider is not registered'));
        }
        $products = $this->providers[$type]->getLinkedProducts($product);
        $converter = $this->converterPool->getConverter($type);
        $output = [];
        $sorterItems = [];
        foreach ($products as $item) {
            $output[$item->getId()] = $converter->convert($item);
        }
        foreach ($output as $item) {
            $itemPosition = (int)$item['position'];
            while (isset($sorterItems[$itemPosition])) {
                $itemPosition++;
            }
            $sorterItems[$itemPosition] = $item;
        }
        ksort($sorterItems);
        return $sorterItems;
    }
}
许可以下: CC-BY-SA归因
scroll top