Hóa ra đây là một lỗi trong Mage_Sales_Model_Quote_Item::compare()
đó đã được giới thiệu trong Magento CE 1.9.2 / EE 1.14.2. Phương pháp được sử dụng để so sánh các mục để quyết định xem chúng có phải là cùng một sản phẩm hay không và có thể được hợp nhất (trong khi đăng nhập và khi thêm sản phẩm vào giỏ hàng).
Khi so sánh tất cả các tùy chọn tùy chỉnh, nên bỏ qua các tùy chọn không phản hồi ( _notRepresentOptions
), cụ thể là tùy chọn info_buyRequest .
Trong các phiên bản Magento trước, nó trông như thế này:
foreach ($this->getOptions() as $option) {
if (in_array($option->getCode(), $this->_notRepresentOptions)) {
continue;
}
và làm việc chính xác. Bây giờ nó trông như thế này:
foreach ($this->getOptions() as $option) {
if (in_array($option->getCode(), $this->_notRepresentOptions)
&& !$item->getProduct()->hasCustomOptions()
) {
continue;
}
và kiểm tra bổ sung cho hasCustomOptions()
nguyên nhân lỗi được mô tả. Tại sao? Có vẻ như kiểm tra đã được thêm vào để luôn giữ các sản phẩm có các tùy chọn tùy chỉnh riêng biệt. Tôi không nghĩ nó có ý nghĩa, ít nhất là không phải theo cách nó được thực hiện, nhưng sẽ có một số lý do cho nó mà tôi không nhận thức được.
Tuy nhiên, $item->getProduct()->hasCustomOptions()
luôn luôn trả về đúng cho các mục báo giá!
Đây là phương pháp:
public function hasCustomOptions()
{
if (count($this->_customOptions)) {
return true;
} else {
return false;
}
}
Nhưng $this->_customOptions
cũng chứa các info_buyRequest
tùy chọn từ các mục trích dẫn.
Đối với một giải pháp không quan trọng, tôi đã cố gắng loại bỏ info_buyRequest
tùy chọn khỏi tất cả các sản phẩm trong một người quan sát trên sales_quote_merge_before
nhưng không thành công.
Lý do nằm ở Mage_Sales_Model_Quote_Item_Abstract::getProduct()
chỗ tùy chọn được sao chép lại từ chính mục trích dẫn:
public function getProduct()
{
$product = $this->_getData('product');
[...]
if (is_array($this->_optionsByCode)) {
$product->setCustomOptions($this->_optionsByCode);
}
return $product;
}
Giải pháp
Tôi đã tạo một bản ghi lại Mage_Sales_Model_Quote_Item
với ghi đè getProduct()
để không bao gồm info_buyRequest
tùy chọn tại thời điểm này:
public function getProduct()
{
$product = parent::getProduct();
$options = $product->getCustomOptions();
if (isset($options['info_buyRequest'])) {
unset($options['info_buyRequest']);
$product->setCustomOptions($options);
}
return $product;
}
Điều này gây ra sự cố với các sản phẩm đi kèm, thay thế bên dưới hoặc bản vá chính thức như được mô tả bởi @ AnnaVölkl là một giải pháp tốt hơn
Thay thế
Bạn cũng có thể loại bỏ vi phạm && !$item->getProduct()->hasCustomOptions()
trong compare()
phương thức nếu bạn đang viết lại mô hình vật phẩm bằng mọi cách. Tôi không biết vấn đề gì nó đã cố gắng giải quyết, nhưng nó đã tạo ra nhiều hơn ...
Cập nhật ngày 29 tháng 1 năm 2016
Tôi đã báo cáo điều này với Magento và nhận được phản hồi rằng họ không thể tái tạo vấn đề, vì vậy bản vá sẽ không được đưa vào phiên bản cộng đồng (Submission APPSEC-1321).
Điều này có nghĩa, nếu bạn gặp sự cố, bạn cần áp dụng bản vá doanh nghiệp SUPEE-6190 sau mỗi lần cập nhật hoặc sử dụng viết lại lớp thay thế.