m2如何创建自定义的reindex索引

2.46K 浏览开发笔记

m2如何创建自定义的reindex索引

比如,创建一个reindex,更新无库存的bundle产品id到stock表。

一,在indexer.xml里定义

<?xml version="1.0"?> 
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nOnamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd">     
<indexer id="zou_test_indexer" view_id="zou_test_indexer" class="ZouTestModelIndexerFixBundleProductStock">       
<title translate="true">Zou Test Indexer</title>
<description translate="true">Fix Bundle Product Stock</description>
</indexer>
</config>

二,在mview.xml里定义

当产品保存时,监听catalog_product_entity表的数据改动,返回产品id给索引器。我们自定义定义的索引获取该产品id,更新无库存的bundle产品id到stock表。

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nOnamespaceSchemaLocation="urn:magento:framework:Mview/etc/mview.xsd">     
<view id="zou_test_indexer" class="ZouTestModelIndexerFixBundleProductStock" group="indexer">         
<subscriptions>             
<table name="catalog_product_entity" entity_column="entity_id" />         
</subscriptions>     
</view> 
</config>

三,在逻辑代码

<?php 
namespace ZouTestModelIndexer; 
use MagentoFrameworkAppObjectManager; 
use MagentoFrameworkAppResourceConnection; 
class FixBundleProductStock implements MagentoFrameworkIndexerActionInterface, MagentoFrameworkMviewActionInterface {     
  protected $_connection;      
  public function __construct(         
    ResourceConnection $resource,         
    MagentoCatalogInventoryModelResourceModelIndexerStockFactory $indexerFactory,         
    MagentoCatalogModelProductType $catalogProductType     
  ) {         
    $this->_resource = $resource;         
    $this->_indexerFactory = $indexerFactory;         
    $this->_catalogProductType = $catalogProductType;     
  }     
  protected function _getTable($entityName)     {         
    return $this->_resource->getTableName($entityName);     
  }     
  public function executeAllBundleProducts($ids=null){       
    $connection = $this->_getConnection();// retrieve product types by processIds           
    $select = $connection->select()->from($this->_getTable('catalog_product_entity'), ['entity_id', 'type_id'])->where('type_id = "bundle"');
    if($ids){
      $select->where('entity_id IN(?)', $ids);
    }         
    $pairs = $connection->fetchPairs($select);
    $bundleProductIds = array_keys($pairs);
    $tableName = $this->_getTable('cataloginventory_stock_status');
    $select = $connection->select()->from($tableName, ['product_id'])->where('product_id IN(?)', $bundleProductIds);
    $stockProducts = $connection->fetchAll($select);
    foreach ($stockProducts as $row) {
      if(isset($pairs[$row['product_id']])){
        unset($pairs[$row['product_id']]);
      }         
    }         
    echo "START ... rn";         
    if($pairs){             
      $num = 0;             
      $total = count($pairs);
      foreach ($pairs as $productId => $typeId) {
        $num ++;                 
        echo "{$productId} ({$num}/{$total}) ... ";                 
        $bind = ['product_id' => $productId,'website_id' => 0,'stock_id' => 1,'qty' => '10000','stock_status' => 1,];
        $connection->insert($tableName, $bind);
        echo "ok!rn";
      }
    }
    echo "ALL DONE!rn";
  }     
  protected function _getConnection()     {
    if (null === $this->_connection) {
      $this->_connection = $this->_resource->getConnection();
    }
      return $this->_connection;
    }       
    /*      * Used by mview, allows process indexer in the "Update on schedule" mode      */     
    public function execute($ids){
      $this->executeAllBundleProducts($ids);         //code here!     
    }       
    /*      * Will take all of the data and reindex      * Will run when reindex via command line      */     
    public function executeFull(){         
      $this->executeAllBundleProducts();         //code here!     
    }               
    /*      * Works with a set of entity changed (may be massaction)      */     
    public function executeList(array $ids){         
      $this->executeAllBundleProducts($ids);         //code here!     
    }               
    /*      * Works in runtime for a single entity using plugins      */     
    public function executeRow($id){         
        $this->executeAllBundleProducts([$id]);         //code here!     
    }
}

四,测试

  php bin/magento indexer:reindex zou_test_indexer

参考

https://www.mageplaza.com/magento-2-module-development/magento-2-indexing.html

0