Magento2 – Remove Products Linked to Another Store View

magento-2.1magento2

In Magento\CatalogImportExport\Model\Export\Product::collectRawData() :

There is the following lines starting at line 904:

$collection = $this->_getEntityCollection();
        foreach ($this->_storeIdToCode as $storeId => $storeCode) {
            $collection->setStoreId($storeId);

I would like to remove the products that are part of a specific store Code as it is causing duplicates during the export.

Is there perhaps a way to get the SQL query that puts the collection for a specific store view together?

Update:

I tried to find catalog_product_entity_* with store_id != 0 but there were none.

I have found that from Magento\CatalogImportExport\Model\Export\Product::collectRawData() the data returned is an associative array.

Consisting of a product for each storeview.
Funny thing is that where there are just 4 attributes per storeview, it is emptied out by this method $this->appendMultirowData($dataRow, $multirawData); but there is a case where more than 4 attributes come back for the storeview and that creates the duplicate on the excel spreadsheet.

Example of array with 4 elements

array(4)
sku:"DLN-22083"
store_id:1
product_id:3485
product_link_id:"3485"

Example of an array with 10 elements

array(10)
description:"<p>My Desc</p>"
technical_specifications:"<ul><li>Red</li></ul>"
_store:"shs_en"
_attribute_set:"Dies"
_type:"simple"
sku:"DLN-14426"
store_id:1
product_id:3484
product_link_id:"3484"

So if I can stop there extra attributes from being added then the product won't be added to the spreadsheet

Best Answer

Actually products are not directly linked to any store view, but their values can be changed at store view level. So you can show different values for different store views.

For example, you have a product with the price $200 in default store view. You can change price for another store view to $100, if you want. The price information is saved in the table catalog_product_entity_decimal.

If you look at the table, you will see that there is a store_id field in it. This field makes it possible for you to define different values for each store view.

mysql> select * from catalog_product_entity_decimal; +----------+--------------+----------+--------+----------+ | value_id | attribute_id | store_id | row_id | value | +----------+--------------+----------+--------+----------+ | 1 | 77 | 0 | 1 | 111.0000 | | 2 | 77 | 0 | 3 | 11.0000 | | 3 | 77 | 0 | 4 | 200.0000 | | 4 | 77 | 0 | 5 | 200.0000 | | 5 | 77 | 0 | 6 | 200.0000 | | 6 | 77 | 0 | 7 | 200.0000 | | 7 | 77 | 0 | 8 | 200.0000 | | 8 | 77 | 0 | 9 | 200.0000 | | 9 | 77 | 1 | 9 | 100.0000 | +----------+--------------+----------+--------+----------+

After all these explanation, let me show how to combine these values. First of all, you need to inject some dependencies in your constructor.

public function __construct(
    \Magento\Framework\App\ResourceConnection $resourceConnection,
)
{
    $this->resourceConnection = $resourceConnection;
}

After that, you can run the following code block. This code block will combine a specific store view with the default one. The store view is stored in the variable $storeViewId.

// This is the specific store view id to be combined
$storeViewId = 1;
$resourceConnection = $this->resourceConnection;

// Get connection adapter
$connection = $resourceConnection->getConnection();

// Get tables names
$tableProductEntityDatetime = $resourceConnection->getTableName('catalog_product_entity_datetime');
$tableProductEntityDecimal = $resourceConnection->getTableName('catalog_product_entity_decimal');
$tableProductEntityInt = $resourceConnection->getTableName('catalog_product_entity_int');
$tableProductEntityText = $resourceConnection->getTableName('catalog_product_entity_text');
$tableProductEntityVarchar = $resourceConnection->getTableName('catalog_product_entity_varchar');

$tableNames = [
    $tableProductEntityDatetime,
    $tableProductEntityInt,
    $tableProductEntityDecimal,
    $tableProductEntityText,
    $tableProductEntityVarchar
];
foreach ($tableNames as $tableName) {
    $rowsAttributes = $connection->fetchAll("SELECT `value_id`, `attribute_id`, `value` FROM `{$tableName}` WHERE `row_id` = :row_id AND `store_id` = :store_view_id", [
        'row_id' => $product->getRowId(),
        'store_view_id' => $storeViewId
    ]);
    foreach ($rowsAttributes as $row) {
        $connection->delete($tableName, "`value_id` = {$row['value_id']}");
        try {
            $connection->insert($tableName, [
                'attribute_id' => $row['attribute_id'],
                'store_id' => 0,
                'row_id' => $product->getRowId(),
                'value' => $row['value']
            ]);
        } catch (\Exception $e) {
            // Entry already created
        }
    }
}
Related Topic