Magento는 PHP로 개발되고 Zend Framework를 사용하여 개발된 전문 오픈 소스 전자 상거래 플랫폼입니다. 그런데 인터넷상의 일부 네티즌들은 마젠토 2.2.5와 2.2.6에 버그가 있다고 주장했는데, 제품이 특별가를 설정하고 삭제한 후, 편집자가 문제를 정리했습니다.
1. 문제 설명: 이 문제는 버전 2.2.5 및 2.2.6에서 발생하며 Magento2의 시스템 버그입니다. 0.5위안과 같이 제품에 대한 특별 가격을 설정합니다. 이 제품을 낮은 가격에서 높은 가격으로 정렬한 다음 특별 가격을 삭제하고 저장한 후 이에 대해 표시되는 가격을 다시 작성합니다. 맞는 상품인데, 표시되어 있어도 가격이 그것보다 저렴하고, 아직도 가격순으로 1위를 차지하고 있는 상품입니다.
2. 문제 위치:
1. 가격 정렬에 문제가 있습니다. 먼저, 데이터베이스에서 가격 관련 데이터 테이블을 찾아보세요. 가격, 가격 정렬이 정확합니다. 문제의 테이블은 Catalog_product_index_price로 식별됩니다.
2. 제품 저장 시 이 테이블의 Catalog_product_index_price의 최종 가격 값이 0으로 저장되는 이유를 확인합니다. 제품 저장은 Vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php 파일과 관련되어 있습니다. 중단점 디버깅이 Catalog_product_index_price 저장 작업을 감지하지 못했습니다. 나중에 동료가 제품을 저장한 후 다시 색인화할 것이라고 상기시켰습니다. 간단한 테스트를 통해 다시 색인화할 때 Catalog_product_index_price 테이블이 실제로 저장되었음을 발견했습니다.
3. 재인덱싱 시 중단점 디버깅을 사용하여 최종적으로 데이터 테이블에 삽입된 SQL 문을 얻습니다. SQL 문을 분석하면 문제의 원인을 확인할 수 있습니다. reindex의 시작점은 Vendor/magento/module-indexer/Console/Command/IndexerReindexCommand.php 파일에 있지만, 가격 reindex 작업을 정확하게 찾으려면 많은 노력과 인내가 필요합니다. 마지막으로, 임시 테이블에 삽입된 SQL 문 $query 변수를 가져올 수 있는 Vendor/magento/module-catalog/Model/ResourceModel/Product/Indexer/Price/SimpleProductPrice.php 파일을 찾아 SQL 문을 복사한 다음 Navicat에 넣어서 실행하면 됩니다. 삽입할 데이터에서 final_price가 0인 것을 확인할 수 있습니다. 다음은 이 SQL 문을 주로 분석한 것입니다.
4. 아래 SQL 문에서 볼 수 있듯이 이 문은 매우 길고 복잡합니다. 첫째, 복잡한 SQL 문을 분석한 경험이 없기 때문에 명확하게 분석해야 합니다. 둘째, 시간이 많이 걸립니다. 동료들의 시연과 조언을 통해 이 SQL 문을 분석하는 것이 생각만큼 어렵지 않다는 것을 알았습니다. 왜냐하면 문이 아무리 복잡하더라도 기본 문으로 구성되어 있지만 여러 레이어의 중첩이 추가되어 if의 판단이 가능하기 때문입니다. 매우 복잡해 보이지만 기본적인 분석 방법은 '분할하여 정복하라'는 중국의 관용어에 풍부한 철학적 지혜가 담겨 있다는 것을 알게 되었습니다. . 다음은 "분열하여 정복하는 방법"과 "서로를 이기는 방법"에 대해 자세히 설명한다.
분할 정복은 이 SQL 문에서 관련 없는 내용을 무시하고 핵심 데이터에만 집중하는 것입니다. final_price에 문제가 있습니다. final_price를 어떻게 구하는지 살펴보고 노란색 배경 부분을 살펴보겠습니다. 가장 바깥쪽 레이어는 IFNULL 판단 레이어입니다. 이는 첫 번째 매개변수가 true이면 자체적으로 반환하고, 그렇지 않으면 final_price가 0이면 첫 번째 매개변수가 FALSE여야 한다고 판단할 수 있음을 의미합니다. . 하지만 첫 번째 매개변수는 긴 단락이므로 주의 깊게 분석해 보겠습니다. 중첩이 많기 때문에 명확하게 확인하기가 쉽지 않습니다. 이때 계층 구조가 더 명확하고 명확해 지도록 형식을 지정하는 외부 도구가 필요합니다. 브래킷의 시작과 끝을 볼 수 있습니다. PHPStorm은 매우 유용한 도구입니다. 이 코드를 복사하여 분석하기 전에 형식을 지정하세요.
코드는 값 비교와 연산을 포함하기 때문에 각각을 분리하여 이러한 다양한 값을 인쇄하고 표시하는 방법을 배운 다음 하나씩 비교 및 분석에 사용해야 합니다. 출력(쿼리)하는 것은 어렵지 않습니다. 그냥 그대로 따라하면 됩니다. IFNULL이나 IF문을 이용하면 됩니다.
5. 위의 분석 결과, 문제는 Special_from_date라는 제품 속성에 있는 것으로 최종 확인되었습니다. Special_price를 저장하면 이 속성의 값도 저장되지만, Special_price를 삭제하면 남아있는 데이터가 위 SQL문의 판단에 영향을 미쳐 final_price의 값이 0이 된다.
6. 문제를 찾은 후 최종 해결 방법입니다. Vendor/magento/module-catalog/Observer/SetSpecialPriceStartDate.php 파일의 실행 메소드를 재정의하고 다음과 같이 변경합니다. 특별 가격이 있으면 특별_from_날짜를 저장하고, 특별 가격이 없으면 특별_from_날짜를 삭제하는 기능입니다. 코드를 업데이트한 후 문제가 해결되었습니다.
/** * Set the current date to Special Price From attribute if it empty * * If special price was deleted, Special Price From attribute will be deleted * * (Important! Otherwise indexer would be confused) * * @param \Magento\Framework\Event\Observer $observer * @return $this */ public function execute(\Magento\Framework\Event\Observer $observer) { /** @var $product \Magento\Catalog\Model\Product */ $product = $observer->getEvent()->getProduct(); if ($product->getSpecialPrice() && !$product->getSpecialFromDate()) { $product->setData('special_from_date', $this->localeDate->date()); } elseif (!$product->getSpecialPrice() && $product->getSpecialFromDate()) { $product->unsetData('special_from_date'); } return $this; }
三、总结:经此,定位问题,解决问题的能力又获得一丁点的提升。主要是学会了对复杂SQL语句的初步分析,知道了IFNULL、IF、LEAST函数的使用,AND比OR的优先级要高的事实。
SQL语句:
INSERT INTO `catalog_product_index_price_temp` SELECT `e`.`entity_id`, `cg`.`customer_group_id`, `pw`.`website_id`, IF(IFNULL(tas_tax_class_id.value_id, -1) > 0, tas_tax_class_id.value, tad_tax_class_id.value) AS `tax_class_id`, IFNULL((ta_price.value), 0) AS `price`, IFNULL((LEAST(ta_price.value, IF(ta_special_price.value IS NOT NULL AND IF(IFNULL(tas_special_from_date.value_id, -1) > 0, tas_special_from_date.value, tad_special_from_date.value) IS NULL OR DATE(IF(IFNULL(tas_special_from_date.value_id, -1) > 0, tas_special_from_date.value, tad_special_from_date.value)) <= cwd.website_date AND IF(IFNULL(tas_special_to_date.value_id, -1) > 0, tas_special_to_date.value, tad_special_to_date.value) IS NULL OR DATE(IF(IFNULL(tas_special_to_date.value_id, -1) > 0, tas_special_to_date.value, tad_special_to_date.value)) >= cwd.website_date, ta_special_price.value, ~0), IFNULL((IF(tier_price_1.value_id is NULL AND tier_price_2.value_id is NULL AND tier_price_3.value_id is NULL AND tier_price_4.value_id is NULL, NULL, LEAST(IFNULL((IF(tier_price_1.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_1.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_1.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_2.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_2.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_2.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_3.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_3.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_3.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_4.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_4.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_4.value * cwd.rate, 4))), ~0)))), ~0))), 0) AS `final_price`, IFNULL((LEAST(ta_price.value, IF(ta_special_price.value IS NOT NULL AND IF(IFNULL(tas_special_from_date.value_id, -1) > 0, tas_special_from_date.value, tad_special_from_date.value) IS NULL OR DATE(IF(IFNULL(tas_special_from_date.value_id, -1) > 0, tas_special_from_date.value, tad_special_from_date.value)) <= cwd.website_date AND IF(IFNULL(tas_special_to_date.value_id, -1) > 0, tas_special_to_date.value, tad_special_to_date.value) IS NULL OR DATE(IF(IFNULL(tas_special_to_date.value_id, -1) > 0, tas_special_to_date.value, tad_special_to_date.value)) >= cwd.website_date, ta_special_price.value, ~0), IFNULL((IF(tier_price_1.value_id is NULL AND tier_price_2.value_id is NULL AND tier_price_3.value_id is NULL AND tier_price_4.value_id is NULL, NULL, LEAST(IFNULL((IF(tier_price_1.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_1.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_1.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_2.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_2.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_2.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_3.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_3.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_3.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_4.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_4.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_4.value * cwd.rate, 4))), ~0)))), ~0))), 0) AS `min_price`, IFNULL((LEAST(ta_price.value, IF(ta_special_price.value IS NOT NULL AND IF(IFNULL(tas_special_from_date.value_id, -1) > 0, tas_special_from_date.value, tad_special_from_date.value) IS NULL OR DATE(IF(IFNULL(tas_special_from_date.value_id, -1) > 0, tas_special_from_date.value, tad_special_from_date.value)) <= cwd.website_date AND IF(IFNULL(tas_special_to_date.value_id, -1) > 0, tas_special_to_date.value, tad_special_to_date.value) IS NULL OR DATE(IF(IFNULL(tas_special_to_date.value_id, -1) > 0, tas_special_to_date.value, tad_special_to_date.value)) >= cwd.website_date, ta_special_price.value, ~0), IFNULL((IF(tier_price_1.value_id is NULL AND tier_price_2.value_id is NULL AND tier_price_3.value_id is NULL AND tier_price_4.value_id is NULL, NULL, LEAST(IFNULL((IF(tier_price_1.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_1.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_1.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_2.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_2.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_2.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_3.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_3.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_3.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_4.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_4.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_4.value * cwd.rate, 4))), ~0)))), ~0))), 0) AS `max_price`, IF(tier_price_1.value_id is NULL AND tier_price_2.value_id is NULL AND tier_price_3.value_id is NULL AND tier_price_4.value_id is NULL, NULL, LEAST(IFNULL((IF(tier_price_1.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_1.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_1.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_2.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_2.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_2.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_3.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_3.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_3.value * cwd.rate, 4))), ~0), IFNULL((IF(tier_price_4.value = 0, ROUND(ta_price.value * (1 - ROUND(tier_price_4.percentage_value * cwd.rate, 4) / 100), 4), ROUND(tier_price_4.value * cwd.rate, 4))), ~0))) AS `tier_price` FROM `catalog_product_entity` AS `e` CROSS JOIN `customer_group` AS `cg` INNER JOIN `catalog_product_website` AS `pw` ON pw.product_id = e.entity_id INNER JOIN `catalog_product_index_website` AS `cwd` ON pw.website_id = cwd.website_id LEFT JOIN `catalog_product_index_tier_price` AS `tp` ON tp.entity_id = e.entity_id AND tp.customer_group_id = cg.customer_group_id AND tp.website_id = pw.website_id LEFT JOIN `catalog_product_entity_tier_price` AS `tier_price_1` ON tier_price_1.row_id = e.row_id AND tier_price_1.all_groups = 0 AND tier_price_1.customer_group_id = cg.customer_group_id AND tier_price_1.qty = 1 AND tier_price_1.website_id = 0 LEFT JOIN `catalog_product_entity_tier_price` AS `tier_price_2` ON tier_price_2.row_id = e.row_id AND tier_price_2.all_groups = 0 AND tier_price_2.customer_group_id = cg.customer_group_id AND tier_price_2.qty = 1 AND tier_price_2.website_id = pw.website_id LEFT JOIN `catalog_product_entity_tier_price` AS `tier_price_3` ON tier_price_3.row_id = e.row_id AND tier_price_3.all_groups = 1 AND tier_price_3.customer_group_id = 0 AND tier_price_3.qty = 1 AND tier_price_3.website_id = 0 LEFT JOIN `catalog_product_entity_tier_price` AS `tier_price_4` ON tier_price_4.row_id = e.row_id AND tier_price_4.all_groups = 1 AND tier_price_4.customer_group_id = 0 AND tier_price_4.qty = 1 AND tier_price_4.website_id = pw.website_id LEFT JOIN `catalog_product_entity_int` AS `tad_tax_class_id` ON tad_tax_class_id.row_id = e.row_id AND tad_tax_class_id.attribute_id = 149 AND tad_tax_class_id.store_id = 0 LEFT JOIN `catalog_product_entity_int` AS `tas_tax_class_id` ON tas_tax_class_id.row_id = e.row_id AND tas_tax_class_id.attribute_id = 149 AND tas_tax_class_id.store_id = cwd.default_store_id INNER JOIN `catalog_product_entity_int` AS `tad_status` ON tad_status.row_id = e.row_id AND tad_status.attribute_id = 97 AND tad_status.store_id = 0 LEFT JOIN `catalog_product_entity_int` AS `tas_status` ON tas_status.row_id = e.row_id AND tas_status.attribute_id = 97 AND tas_status.store_id = cwd.default_store_id LEFT JOIN `catalog_product_entity_decimal` AS `ta_price` ON ta_price.row_id = e.row_id AND ta_price.attribute_id = 77 AND ta_price.store_id = 0 LEFT JOIN `catalog_product_entity_decimal` AS `ta_special_price` ON ta_special_price.row_id = e.row_id AND ta_special_price.attribute_id = 78 AND ta_special_price.store_id = 0 LEFT JOIN `catalog_product_entity_datetime` AS `tad_special_from_date` ON tad_special_from_date.row_id = e.row_id AND tad_special_from_date.attribute_id = 79 AND tad_special_from_date.store_id = 0 LEFT JOIN `catalog_product_entity_datetime` AS `tas_special_from_date` ON tas_special_from_date.row_id = e.row_id AND tas_special_from_date.attribute_id = 79 AND tas_special_from_date.store_id = cwd.default_store_id LEFT JOIN `catalog_product_entity_datetime` AS `tad_special_to_date` ON tad_special_to_date.row_id = e.row_id AND tad_special_to_date.attribute_id = 80 AND tad_special_to_date.store_id = 0 LEFT JOIN `catalog_product_entity_datetime` AS `tas_special_to_date` ON tas_special_to_date.row_id = e.row_id AND tas_special_to_date.attribute_id = 80 AND tas_special_to_date.store_id = cwd.default_store_id WHERE ((IF(IFNULL(tas_status.value_id, -1) > 0, tas_status.value, tad_status.value) = 1) AND (e.type_id = 'simple') AND (e.entity_id BETWEEN 2 AND 21)) AND (e.created_in <= '1546224120') AND (e.updated_in > '1546224120')
위 내용은 Magento 2.2.5, 2.2.6 제품 특가 설정 후 삭제 문제 분석 및 해결의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!