Magento Community Edition 1.8以降でプロモーションルールが夜中に外れる問題
この記事は公開から 1年以上が経過しています。現在の最新情報との整合性については弊社では一切の責任を負いかねます。
Magentoはシステムの内部時間として世界標準時(UTC)を使います。
そのため、Magentoのデータベースの中を見ると、あらゆる時間がUTCで記録されるため、日本時間に慣れている日本人の目からは奇妙に映るかもしれません。
ですがこれは初期バージョンからずっと変わらない仕様です。
さて、Magento Community Edition 1.8以降では「カタログ価格ルール」の日付判定処理が変わったため、ルールが夜中に外れる問題が発生することがあります。
ルールが当たらない原因
ルールが当たらない原因は非常に単純です。
「ルールを適用するかどうかの基準になる日付の処理が、Magento Community Edition 1.8で変更になったため、それまでのバージョンと異なる動きをするようになった」、というのが理由です。
たったそれだけの理由ですが、場合によっては深刻な問題、つまり夜中になると勝手にルールが外れてしまうという問題に発展することがあります。
何が変わったのか?
1.7までは以下のようにMagento側のVarien_Dateクラスを用いて日付を作成し、UTC日付に置き換えて、データベースに渡していました。
/**
* Format date to internal format
*
* @param string|Zend_Date|true|null $date
* @param boolean $includeTime
* @return string|null
*/
public static function formatDate($date, $includeTime = true)
{
if ($date === true) {
return self::now(!$includeTime);
}
if ($date instanceof Zend_Date) {
if ($includeTime) {
return $date->toString(self::DATETIME_INTERNAL_FORMAT);
} else {
return $date->toString(self::DATE_INTERNAL_FORMAT);
}
}
if (empty($date)) {
return null;
}
if (!is_numeric($date)) {
$date = self::toTimestamp($date);
}
$format = $includeTime ? self::DATETIME_PHP_FORMAT : self::DATE_PHP_FORMAT;
return date($format, $date);
}
1.8以降では、Magento側ではMage_Core_Helper_Dateで生成したUNIXタイムスタンプを直接データベースに渡し、データベース内で日付に変換しています。
/** @var $coreDate Mage_Core_Model_Date */
$coreDate = $this->_factory->getModel('core/date');
$timestamp = $coreDate->gmtTimestamp('Today');
foreach ($this->_app->getWebsites(false) as $website) {
/** @var $website Mage_Core_Model_Website */
if ($website->getDefaultStore()) {
$this->_reindex($website, $timestamp);
}
}
結局問題は何なのか?
原因はデータベースの時間です。
Magentoが使うデータベースはMySQLです。MySQLにはタイムゾーンの設定パラメータがあり、大半のMySQLはサーバーの時間を使うようになっています。ですから、サーバーの時間にJSTを使っていたとしても症状が顕在化することはありません。
問題が起きる環境とは?
問題が起きる環境は、Magentoの時間とデータベースの時間が異なる環境です。
海外にあるサーバーを使っていて、JST以外の時間がデータベースの時間になっている場合は注意したほうが良いでしょう。
(もちろん、日本国内のサーバーでも同様です。データベース時間がUTCになっている場合はどの環境でも発生します)
なお、Amazon RDSを使っている場合は、東京リージョンであってもデータベースの時間はUTCになっています。
パラメータグループでも直すことができないので、この環境だけはどうにもなりません。
Amazon RDSを使っている場合は
Amazon RDSを使っている場合は、以下の修正をすることで問題を解決できます。
Mage_CatalogRule_Model_Action_Index_Refreshの120行目付近を以下のように修正
/** @var $coreDate Mage_Core_Model_Date */
//$coreDate = $this->_factory->getModel('core/date');
//$timestamp = $coreDate->gmtTimestamp('Today');
$timestamp = Mage::app()->getLocale()->date(date('Y-m-d H:i:s'))->add(GMTからの時差, Zend_Date::HOUR)->get(Zend_Date::TIMESTAMP);
参考にしてみてください。(GMTより遅れる地域の場合はaddではなくsubする必要があるかもしれません)