ホームページ  >  記事  >  バックエンド開発  >  Magento 2.2.5 および 2.2.6 製品の特別価格設定と削除の問題の分析と解決策

Magento 2.2.5 および 2.2.6 製品の特別価格設定と削除の問題の分析と解決策

little bottle
little bottle転載
2019-04-16 15:06:202211ブラウズ

Magento は、PHP で開発され、Zend Framework を使用するプロフェッショナルなオープンソース e コマース プラットフォームです。しかし、インターネット上の一部のネチズンは、Magento 2.2.5と2.2.6にバグがあり、製品に特別価格を設定して削除した後、価格の並べ替えが間違っていたと編集者が問題をまとめました。

1. 問題の説明: この問題はバージョン 2.2.5 および 2.2.6 に存在し、Magento2 のシステム バグです。商品に特別価格 (0.5 元など) を設定します。この商品を価格の安い順に並べ替えると、最初にランク付けされます。その後、特別価格を削除して保存し、インデックスを再構築します。この商品に表示される価格は、商品は正しいですが、表示されていてもこの商品よりも価格が安く、価格的には依然としてこの商品が1位です。

2. 問題の場所:
1. 価格の並べ替えに問題があります。データ ストレージに問題があるはずです。まず、データベース内の価格関連のデータテーブルを探し、catalog_product_index_priceとcatalog_category_entity_decmalを合わせて見ると、問題のある商品のうち、final_price max_price min_priceの値がすべて0であることがわかり、価格と同じ値に変更すると、価格の並べ替えは正しいです。問題のテーブルは、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 ステートメントを分析する限り、問題の原因を特定できます。再インデックスの開始点はファイル Vendor/magento/module-indexer/Console/Command/IndexerReindexCommand.php にありますが、インデクサーは多数あるため、価格の再インデックス操作を正確に見つけるには多大な労力と忍耐が必要です。最後に、vendor/magento/module-catalog/Model/ResourceModel/Product/Indexer/Price/SimpleProductPrice.php ファイルを見つけます。このファイルから、一時テーブルに挿入された SQL ステートメント $query 変数を取得し、SQL ステートメントをコピーして、これをNavicatに入れて実行すると、挿入するデータの中で、final_priceが0になっていることがわかります。以下では主にこのSQL文を解析します。

4. 以下に示す SQL ステートメントに示されているように、このステートメントは非常に長く複雑です。内部の論理構造を明確に分析することは非常に困難です。第一に、複雑な SQL ステートメントを分析した経験がありません。第二に、非常に時間がかかります。同僚からのデモンストレーションとリマインダーの後、この SQL ステートメントの分析は想像ほど難しくないことがわかりました。ステートメントがどれほど複雑であっても、ステートメントは基本的なステートメントで構成されていますが、複数のネスト層が追加され、if の判断が行われるためです。非常に複雑に聞こえますが、基本的な分析方法は「分割して征服し、それぞれを倒す」です。この中国の慣用句には豊かな哲学的知恵が含まれています。現実のすべての問題はこの理論で解決できることがわかりました。 。 「分割統治」と「倒し合い」の方法については、以下で詳しく説明します。
分割統治とは、この SQL ステートメント内の無関係なものを無視し、コア データのみに焦点を当てることです。 Final_price に問題があります。final_price がどのように求められるかを見て、黄色の背景の部分を見てみましょう。最外層は IFNULL 判定の層で、第一引数が true の場合は自身を返し、そうでない場合は第二引数を返すという意味で、final_price が 0 になっているので、第一引数は FALSE でなければならないと判断できます。 。ただし、最初のパラメータは長い段落です。注意深く分析してみましょう。ネストが多いため、はっきりと見るのは簡単ではありません。現時点では、階層構造がより明確でわかりやすいように、外部ツールを導入してフォーマットする必要があります。 be 括弧の始まりと終わりを参照してください。 PHPStorm は非常に便利なツールなので、分析する前にこのコードをコピーしてフォーマットしてください。
それぞれを分解します。コードには値の比較と操作が含まれるため、これらのさまざまな値を出力および表示し、比較と分析に 1 つずつ使用する方法を学習する必要があります。印刷(クエリ)するのは難しくなく、それ自体を真似するだけで、IFNULLやIF文を使ってクエリすることができます。

5. 上記の分析の結果、最終的に、special_from_date という製品属性に問題があることが判明しました。 special_price を保存するとこの属性の値も保存されますが、special_price を削除しても削除されず、残ったデータが上記 SQL 文の判定に影響を与えるため、final_price の値が 0 になります。

6. 問題を特定したら、それが最終的な解決策です。 Vendor/magento/module-catalog/Observer/SetSpecialPriceStartDate.php ファイルの実行メソッドをオーバーライドし、次のように変更します。その機能は、special_price がある場合は、special_from_date を保存し、special_price がない場合は、special_from_date を削除することです。コードを更新した後、問題は解決されました。

 /**
* 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;
}

phpビデオチュートリアル

三、总结:经此,定位问题,解决问题的能力又获得一丁点的提升。主要是学会了对复杂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 <= &#39;1546224120&#39;) AND (e.updated_in > '1546224120')

mysql视频教程

以上がMagento 2.2.5 および 2.2.6 製品の特別価格設定と削除の問題の分析と解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。