Download - Индексирование в Magento
![Page 1: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/1.jpg)
Индексация в Magento
Виктор ТихончукMagento System Architect
![Page 2: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/2.jpg)
Модуль Mage_Index
События
Индекс
Индексатор
Процесс
![Page 3: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/3.jpg)
Событие
Mage_Index_Model_Event
Событие – то, что происходит в некоторый момент времени и рассматривается как изменение состояния сущности.
Событие хранит информацию о сущности, с которой произошло действие и тип действия.
Типы изменений сущности (event type)• Сохранение (SAVE)
• Удаление (DELETE)
• Групповая обработка (MASS_ACTION)
![Page 4: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/4.jpg)
Обработчик
Mage_Index_Model_Indexer
• processEntityAction($entity, $entityType, $eventType)
• logEvent($entity, $entityType, $eventType)
• registerEvent(Mage_Index_Model_Event $event)
• indexEvent(Mage_Index_Model_Event $event)
• indexEvents($entity = null, $type = null)
![Page 5: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/5.jpg)
Изменения в абстрактной модели
Процесс сохранения• _getResource()->beginTransaction()
• _beforeSave()
• _getResource()->save()
• _afterSave()
• _getResource()->commit()
• afterCommitCallback()
Новые события• model_save_commit_after
• {eventPrefix}_save_commit_after
![Page 6: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/6.jpg)
Изменения в абстрактной модели
Процесс удаления• _getResource()->beginTransaction()
• _beforeDelete()
• _getResource()->delete()
• _afterDelete()
• _getResource()->commit()
• _afterDeleteCommit()
Новые события• model_delete_commit_after
• {eventPrefix}_delete_commit_after
![Page 7: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/7.jpg)
Сущности
• catalog/product (SAVE, DELETE, MASS_ACTION)
• catalog/category (SAVE, DELETE)
• catalog/resource_eav_attribute (SAVE, DELETE)
• customer/group (SAVE)
• cataloginventory/stock_item (SAVE)
• tag/tag (SAVE)
• core/store (SAVE, DELETE)
• core/store_group (SAVE, DELETE)
• core/website (SAVE, DELETE)
![Page 8: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/8.jpg)
Процессы и индексаторы
Индексатор может работать в 2х режимах:
• в режиме реального времени (MODE_REAL_TIME)
• в ручном режиме (MODE_MANUAL)
У каждого индексатора есть текущий статус:
• работает (STATUS_RUNNING)
• режим ожидания (STATUS_PENDING)
• необходимо перестроить (STATUS_REQUIRE_REINDEX)
REQUIRE_REINDEXMODE MANUAL
New Indexer
Событие
![Page 9: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/9.jpg)
Процесс
Mage_Index_Model_Process
• matchEvent(Mage_Index_Model_Event $event)
• register(Mage_Index_Model_Event $event)
• processEvent(Mage_Index_Model_Event $event)
• reindexAll()
• reindexEverything()
• indexEvents()
• changeStatus($status)
• getIndexer()
![Page 10: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/10.jpg)
CatalogInventory Stock Status
Цель оптимизировать затраты на подсчет возможности
покупки товара при отображении товаров в каталоге, поиске и т.д.
Мотивация для простых (simple) товаров - динамически определить
доступность не является трудозатратной операцией, чего не скажешь о составных (composite), для которых нужно учитывать статус всех его составляющих
Задача сделать предварительно подсчитанный статус для
каждого товара с учетом склада и веб сайта
![Page 11: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/11.jpg)
Шаг 1: Структура данных индекса
cataloginventory/stock_status
product_id
website_id
stock_id
qty
stock_status
![Page 12: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/12.jpg)
Шаг 2: Создаем индексатор
Mage_CatalogInventory_Model_Indexer_Stock
![Page 13: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/13.jpg)
Шаг 2: Создаем индексатор
Mage_CatalogInventory_Model_Indexer_Stock
Mage_Index_Model_Indexer_Abstract
![Page 14: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/14.jpg)
Шаг 2: Создаем индексатор
Mage_CatalogInventory_Model_Indexer_Stock
Mage_Core_Model_Abstract
Mage_Index_Model_Indexer_Abstract
![Page 15: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/15.jpg)
Шаг 2: Создаем индексатор
Mage_CatalogInventory_Model_Mysql4_Indexer_Stock
Mage_Core_Model_Mysql4_Abstract
Mage_Index_Model_Mysql4_Indexer_Abstract
Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Indexer_Abstract
![Page 16: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/16.jpg)
Шаг 2: Создаем индексатор
Абстрактные методы индексатора• getName()
• getDescription()
• _registerEvent()
• _processEvent()
![Page 17: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/17.jpg)
Шаг 3: Событияprotected $_matchedEntities = array( Mage_CatalogInventory_Model_Stock_Item::ENTITY => array( Mage_Index_Model_Event::TYPE_SAVE ), Mage_Catalog_Model_Product::ENTITY => array( Mage_Index_Model_Event::TYPE_SAVE, Mage_Index_Model_Event::TYPE_MASS_ACTION, Mage_Index_Model_Event::TYPE_DELETE ), Mage_Core_Model_Store::ENTITY => array( Mage_Index_Model_Event::TYPE_SAVE ), Mage_Core_Model_Store_Group::ENTITY => array( Mage_Index_Model_Event::TYPE_SAVE ), Mage_Core_Model_Config_Data::ENTITY => array( Mage_Index_Model_Event::TYPE_SAVE ), Mage_Catalog_Model_Convert_Adapter_Product::ENTITY => array( Mage_Index_Model_Event::TYPE_SAVE ));
![Page 18: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/18.jpg)
Шаг 4: Изменение конфигурацииprotected $_relatedConfigSettings = array( Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK, Mage_CatalogInventory_Helper_Data::XML_PATH_SHOW_OUT_OF_STOCK);
public function matchEvent(Mage_Index_Model_Event $event){ // check saved result in $event and return it if ($entity == Mage_Core_Model_Config_Data::ENTITY) { $configData = $event->getDataObject(); $path = $configData->getPath(); if (in_array($path, $this->_relatedConfigSettings)) { $result = $configData->isValueChanged(); } else { $result = false; } } else { $result = parent::matchEvent($event); } // save result in $event and return it}
![Page 19: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/19.jpg)
Шаг 5: Регистрация событияprotected function _registerEvent(Mage_Index_Model_Event $event){ switch ($event->getEntity()) { case Mage_Catalog_Model_Product::ENTITY: $this->_registerCatalogProductEvent($event); break; // skip some cases case Mage_Core_Model_Store::ENTITY: case Mage_Core_Model_Config_Data::ENTITY: $reindex = Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX; $event->addNewData('skip_call_event_handler', true); $process = $event->getProcess(); $process->changeStatus($reindex); if ($event->getEntity() == Mage_Core_Model_Config_Data::ENTITY) { $configData = $event->getDataObject(); $indexer = Mage::getSingleton('index/indexer'); if ($configData->getPath() == XML_PATH_SHOW_OUT_OF_STOCK) { $index->getProcessByCode('catalog_product_price') ->changeStatus($reindex); $indexer->getProcessByCode('catalog_product_attribute') ->changeStatus($reindex); } } break; }}
![Page 20: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/20.jpg)
Шаг 5: Регистрация событияprotected function _registerCatalogProductDeleteEvent (Mage_Index_Model_Event $event){ /** @var $product Mage_Catalog_Model_Product */ $product = $event->getDataObject(); $parentIds = $this->_getResource() ->getProductParentsByChild($product->getId()); if ($parentIds) { $event->addNewData('reindex_stock_parent_ids', $parentIds); } return $this;}
![Page 21: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/21.jpg)
Шаг 6: Обработка событияprotected function _processEvent(Mage_Index_Model_Event $event){ $data = $event->getNewData(); if (!empty($data['cataloginventory_stock_reindex_all'])) { $this->reindexAll(); } if (empty($data['skip_call_event_handler'])) { $this->callEventHandler($event); }}
![Page 22: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/22.jpg)
Шаг 7: Ресурс модель
Resource Model
Type Indexer Interface
Type Indexer Default
Type Indexer Configurable
![Page 23: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/23.jpg)
Шаг 7: Ресурс модель protected function _getTypeIndexers() { if (is_null($this->_indexers)) { $this->_indexers = array(); $types = Mage::getSingleton('catalog/product_type') ->getTypesByPriority(); foreach ($types as $typeId => $typeInfo) { if (isset($typeInfo['stock_indexer'])) { $modelName = $typeInfo['stock_indexer']; } else { $modelName = $this->_defaultIndexer; } $isComposite = !empty($typeInfo['composite']); $indexer = Mage::getResourceModel($modelName) ->setTypeId($typeId) ->setIsComposite($isComposite);
$this->_indexers[$typeId] = $indexer; } } return $this->_indexers; }
![Page 24: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/24.jpg)
Шаг 7: Ресурс модель public function reindexAll() { $this->useIdxTable(true); $this->clearTemporaryIndexTable();
foreach ($this->_getTypeIndexers() as $indexer) { $indexer->reindexAll(); }
$this->syncData(); return $this; }
![Page 25: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/25.jpg)
Шаг 7: Ресурс модель public function catalogProductDelete(Mage_Index_Model_Event $event) { $data = $event->getNewData(); if (empty($data['reindex_stock_parent_ids'])) { return $this; }
$adapter = $this->_getWriteAdapter();
$parentIds = array(); foreach ($data['reindex_stock_parent_ids'] as $parentId => $parentType) { $parentIds[$parentType][$parentId] = $parentId; }
$adapter->beginTransaction(); try { foreach ($parentIds as $parentType => $entityIds) { $this->_getIndexer($parentType)->reindexEntity($entityIds); } } catch (Exception $e) { $adapter->rollback(); throw $e; }
$adapter->commit();
return $this; }
![Page 26: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/26.jpg)
Шаг 8: Ресурс модели (TYPE Default) public function setTypeId($typeId) { $this->_typeId = $typeId; return $this; }
public function getTypeId() { if (is_null($this->_typeId)) { Mage::throwException(Mage::helper('cataloginventory') ->__('Undefined product type.')); } return $this->_typeId; } public function reindexAll() { $this->useIdxTable(true); $this->_prepareIndexTable(); return $this; } public function reindexEntity($entityIds) { $this->_updateIndex($entityIds); return $this; }
![Page 27: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/27.jpg)
Шаг 9: Декларация индексатора<config> <!-- ... --> <global> <!-- ... --> <index> <indexer> <cataloginventory_stock> <model>cataloginventory/indexer_stock</model> </cataloginventory_stock> <catalog_product_attribute> <depends> <cataloginventory_stock /> </depends> </catalog_product_attribute> <catalog_product_price> <depends> <cataloginventory_stock /> </depends> </catalog_product_price> </indexer> </index> </global></config>
![Page 28: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/28.jpg)
Индекс цен для B2B
Цель Создать новый тип товара B2B
Справка В2В – сокращение от английских слов «business to business»,
в буквальном переводе – бизнес для бизнеса. Это сектор рынка, который работает не на конечного, рядового потребителя, а на такие же компании, то есть на другой бизнес.
Задача Новый тип товара, который наследует поведение простого
товара (simple), но имеет возможность указать цену для каждой группы пользователей (customer group)
![Page 29: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/29.jpg)
Индекс цен для B2B
public function reindexAll();public function reindexEntity($entityIds);public function registerEvent(Mage_Index_Model_Event $event);
Знакомство с интерфейсом Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Indexer_Price_Interface
Создаем свой индексатор
class Mageconf_B2b_Model_Mysql4_Indexer_Price extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Indexer_Price_Default{}
![Page 30: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/30.jpg)
Индекс цен для B2B
public function reindexAll(){ $this->useIdxTable(true); $this->_prepareFinalPriceData(); $this->_applyCustomOption(); $this->_movePriceDataToIndexTable(); return $this;}
public function reindexEntity($entityIds){ $this->_prepareFinalPriceData($entityIds); $this->_applyCustomOption(); $this->_movePriceDataToIndexTable();
return $this;}
Знакомство с … Indexer_Price_Default
![Page 31: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/31.jpg)
Индекс цен для B2B
protected function _getDefaultFinalPriceTable(){ if ($this->useIdxTable()) { return $this->getTable('catalog/product_price_indexer_final_idx'); } return $this->getTable('catalog/product_price_indexer_final_tmp');}
![Page 32: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/32.jpg)
Индекс цен для B2Bcatalog/product_price_indexer_final_*
entity_id
customer_group_id
website_id
tax_class_id
orig_price
price
min_price
max_price
tier_price
base_tier
![Page 33: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/33.jpg)
Индекс цен для B2Bprotected function _prepareFinalPriceData($entityIds = null){ // удаляем данные из таблицы, если они есть $this->_prepareDefaultFinalPriceTable();
$write = $this->_getWriteAdapter(); $select = $write->select() ->from(array('e' => $this->getTable('catalog/product')), array('entity_id')) ->joinCross( array('cg' => $this->getTable('customer/customer_group')), array('customer_group_id')) ->joinCross( array('cw' => $this->getTable('core/website')), array('website_id')) ->join( array('cwd' => $this->_getWebsiteDateTable()), 'cw.website_id = cwd.website_id', array()) ->join( array('csg' => $this->getTable('core/store_group')), 'csg.website_id = cw.website_id AND cw.default_group_id = csg.group_id', array()) ->join( array('cs' => $this->getTable('core/store')), 'csg.default_store_id = cs.store_id AND cs.store_id != 0', array()); // next slide
![Page 34: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/34.jpg)
Индекс цен для B2B // protected function _prepareFinalPriceData($entityIds = null) $select ->join( array('pw' => $this->getTable('catalog/product_website')), 'pw.product_id = e.entity_id AND pw.website_id = cw.website_id', array()) ->joinLeft( array('tp' => $this->_getTierPriceIndexTable()), 'tp.entity_id = e.entity_id AND tp.website_id = cw.website_id' . ' AND tp.customer_group_id = cg.customer_group_id', array()) ->join( array('b2d' => $this->getTable('b2b/price')), 'b2d.entity_id = e.entity_id AND b2d.customer IS NULL AND website_id=0' array()) ->join( array('b2w' => $this->getTable('b2b/price')), 'b2w.entity_id = e.entity_id AND b2w.customer = cg.customer_group_id' . ' AND b2w.website_id = cw.website_id', array()) ->where('e.type_id=?', $this->getTypeId());
$statusCond = $write->quoteInto('=?', Mage_Catalog_Model_Product_Status::STATUS_ENABLED); $this->_addAttributeToSelect($select, 'status', 'e.entity_id', 'cs.store_id', $statusCond, true);
![Page 35: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/35.jpg)
Индекс цен для B2B // protected function _prepareFinalPriceData($entityIds = null)
$taxClassId = $this->_addAttributeToSelect($select, 'tax_class_id', 'e.entity_id', 'cs.store_id'); $select->columns(array('tax_class_id' => $taxClassId));
$finalPrice = new Zend_Db_Expr('IFNULL(b2w.price, b2d.price)');
$select->columns(array( 'orig_price' => $price, 'price' => $finalPrice, 'min_price' => $finalPrice, 'max_price' => $finalPrice, 'tier_price' => new Zend_Db_Expr('NULL'), 'base_tier' => new Zend_Db_Expr('NULL'), ));
if (!is_null($entityIds)) { $select->where('e.entity_id IN(?)', $entityIds); }
![Page 36: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/36.jpg)
Индекс цен для B2B // protected function _prepareFinalPriceData($entityIds = null)
Mage::dispatchEvent('prepare_catalog_product_index_select', array( 'select' => $select, 'entity_field' => new Zend_Db_Expr('e.entity_id'), 'website_field' => new Zend_Db_Expr('cw.website_id'), 'store_field' => new Zend_Db_Expr('cs.store_id') ));
$query = $select->insertromSelect($this->_getDefaultFinalPriceTable()); $write->query($query);
return $this;}
public function registerEvent(Mage_Index_Model_Event $event){ $entity = $event->getEntity(); if ($entity == Mage_Catalog_Model_Product::ENTITY) { if ($event->getType() == Mage_Index_Model_Event::TYPE_SAVE) { // check attributes // add data to event } }}
![Page 37: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/37.jpg)
Обзор индексаторов в Magento
• Product Attributes
• Product Prices
• Catalog URL Rewrites
• Product Flat Data
• Category Flat Data
• Category Products
• Catalog Search Index
• Stock Status
• Tag Aggregation Data
![Page 38: Индексирование в Magento](https://reader035.vdocuments.pub/reader035/viewer/2022081421/555e190cd8b42a99188b571c/html5/thumbnails/38.jpg)
Спасибо за вниманиеEmail: [email protected]