2013-02-13 36 views
18

Sử dụng back-office của Magento, sau khi lưu một danh mục được liên kết với nhiều sản phẩm, chỉ 1000 sản phẩm đầu tiên (hoặc 2000 hoặc x000 tùy thuộc vào cấu hình máy chủ) được lưu giữ.Tại sao Magento chỉ giữ 1000 sản phẩm đầu tiên trong một danh mục, sau khi lưu danh mục?

Tất cả các liên kết danh mục/sản phẩm khác sẽ bị xóa khỏi bảng catalog_category_product trong cơ sở dữ liệu.
Điều này xảy ra mặc dù không có hộp kiểm nào được bỏ chọn trong lưới sản phẩm (tab Sản phẩm danh mục).

Không có thông báo lỗi nào được hiển thị hoặc được ghi lại.
Dữ liệu theo dõi được đăng từ trình duyệt đến máy chủ không tiết lộ bất kỳ ID sản phẩm nào bị thiếu, nhưng ngay cả khi bạn kiểm tra nhiều sản phẩm hơn trên lưới back-office, khi cuối cùng lưu danh mục, máy chủ chỉ giữ x000 đầu tiên và loại bỏ ID ...

Trả lời

27

Mặc dù một số câu trả lời có thể được tìm thấy trên các trang web khác, tôi nghĩ rằng nó là giá trị chia sẻ này trên StackOverflow ...

các nguồn gốc của vấn đề có thể được tìm thấy trong Mage_Adminhtml_Catalog_CategoryController, nơi saveAction() phương pháp lấy một chuỗi được đăng lớn (category_products, được mã hóa như chuỗi truy vấn), được xử lý bằng hàm PHP parse_str():

if (isset($data['category_products']) && !$category->getProductsReadonly()) { 
    $products = array(); 
    parse_str($data['category_products'], $products); 
    $category->setPostedProducts($products); 
} 

Than ôi! Từ phiên bản 5.3.9 của PHP, có một cài đặt cấu hình mới được gọi là max_input_vars, giới hạn số biến đầu vào có thể được chấp nhận.
Giới hạn này chủ yếu được áp dụng cho $_GET, $_POST$_COOKIE superglobals, nhưng cũng được sử dụng nội bộ theo chức năng parse_str()!
(Xem PHP manual)

Tùy thuộc vào cấu hình php.ini của máy chủ của bạn, số lượng sản phẩm có liên quan đến một loại là do bị giới hạn bởi khung cảnh này ...

Một giải pháp là để tăng giá trị của max_input_vars, trong php.ini hoặc trong .htaccess:

<IfModule mod_php5.c> 
    php_value max_input_vars 10000 
</IfModule> 

này thậm chí có thể được thực hiện một cách an toàn hơn bằng cách thay đổi thiết lập này chỉ dành cho trang quản trị (Thích nghi với mô hình LocationMatch để riêng phong cách URL back-office của bạn):

<LocationMatch "mymagentostore/(index\.php/)?admin/"> 
    <IfModule mod_php5.c> 
     php_value max_input_vars 10000 
    </IfModule> 
</LocationMatch> 

(Source)

này chỉ giải quyết vấn đề cho đến khi một trong những hạng mục của bạn đạt đến số lượng tối đa mới của sản phẩm ...

Một giải pháp khác sẽ sửa mã của Magento theo thứ tự không phải để sử dụng hàm parse_str() tại thời điểm này.
Ví dụ, trong Mage_Adminhtml_Catalog_CategoryController, saveAction() phương pháp, thay thế:

parse_str($data['category_products'], $products); 

với:

$cat_products_split = explode('&', $data['category_products']); 
foreach($cat_products_split as $row) { 
    $arr = array(); 
    parse_str($row, $arr); //This will always work 
    list($k, $v) = each($arr); 
    if (!empty($k) && !empty($v)) { 
     $products[$k] = $v; 
    } 
} 

(Source)

Thật khó để quyết định giải pháp là tốt nhất, vì là người đầu tiên làm cho máy chủ của bạn dễ bị tấn công hơn (vì max_input_vars có nghĩa là giảm thiểu khả năng tấn công từ chối dịch vụ sử dụng va chạm băm) và giải pháp thứ hai làm cho bạn sửa đổi một lớp cốt lõi Magento, có thể dẫn đến các vấn đề khác trong việc nâng cấp Magento trong tương lai ...

Hy vọng điều này là hữu ích, tôi đã gặp khó khăn một chút trước khi tìm hiểu lý do tại sao một số danh mục bị mất một số sản phẩm !

+0

Bạn có thấy vấn đề với việc tăng điều này lên hơn 10.000 không? Chúng tôi có một số loại với hơn 31.000 sản phẩm ... –

+0

Vâng, tôi đoán bạn có thể tăng giới hạn cho bất kỳ số nào (tuy nhiên, hiểu rằng điều này làm cho máy chủ của bạn dễ bị tấn công hơn đối với một số cuộc tấn công DoS). – programmeurweb

+0

Đối với giải pháp thứ hai, không thể bạn chỉ cần ghi đè lên bộ điều khiển từ một mô-đun tùy chỉnh. Điều này sẽ làm cho nó nâng cấp an toàn vì tệp lõi vẫn chưa được sửa đổi. – russjman

0

<IfModule mod_php5.c> php_value max_input_vars 10000 </IfModule>

đã làm các trick cho tôi, tôi đã có cùng một vấn đề như mô tả ở trên, Magento 1.4.1.1 chỉ lưu 1001 sản phẩm trong thể loại, nhưng sau khi đặt mã trên trong .htaccess của tôi lỗi này là ra đi .

0

LocationMatch không được phép trong .htaccess, nó có thể được chỉ đặt trong Apache httpd.conf

Cách ưa thích là để tạo ra một Apache bao gồm và không sửa đổi httpd.conf trực tiếp vì nó sẽ phá vỡ trên tiếp theo updare/xây dựng lại.

Trong trường hợp của tôi, tôi đã tạo ra một tập tin bao gồm pre_virtualhost_global.conf và đặt mã này bên trong:

<LocationMatch "mymagentostore/(index\.php/)?admin/"> 
<IfModule mod_php5.c> 
    php_value max_input_vars 10000 
</IfModule> 

Sau đó tất nhiên, bạn cần phải khởi động lại apache. Tôi sử dụng WebHostManager của tôi vì vậy nó là một quá trình dễ dàng.

Thông tin thêm có thể được tìm thấy tại địa chỉ:

http://docs.cpanel.net/twiki/bin/view/EasyApache3/WebHome#Custom Directives to http.conf

Tôi nghĩ rằng đây là giải pháp thanh lịch nhất, không chạm Magento Core, áp dụng cho tất cả các trang web trên máy chủ của bạn và cũng có thể bảo vệ front-end.

1

Tôi đã tìm được giải pháp làm việc để tôi chia sẻ nó ở đây!

Tạo một tên tập tin php5.ini trong thư mục magento root của bạn và trong dòng đầu tiên chỉ cần đặt mã này

[PHP] 
max_input_vars = 5000 

Bây giờ nếu nó không làm việc, bạn sẽ cần phải thêm dòng này trong bạn MÁY CHỦ PHP, ini (/ usr /local/lib/php.ini)

max_input_vars = 5000 

Hy vọng sự trợ giúp của nó.

5

Giải pháp tốt nhất là sử dụng sự kiện quan sát "catalog_category_prepare_save". Vì vậy, bạn cần phải thay đổi cấu hình.xml của bạn mô-đun:

<config> 
    <global> 
     <events> 
      ... 
      <catalog_category_prepare_save> 
       <observers> 
        <your_module> 
         <class>your_module/observer</class> 
         <method>onCatalogCategoryPrepareSave</method> 
        </your_module> 
       </observers> 
      </catalog_category_prepare_save> 

Sau đó, thêm chức năng để ứng dụng/code/local/bạn/Module/mẫu/Observer.php

<?php 
class Your_Module_Model_Observer 
{ 
    /** 
    * Fix bug with saving only first 1000 products in a category 
    * It's related to default php config 'max_input_vars' = 1000 
    * 
    * @param Varien_Event_Observer $observer 
    */ 
    public function onCatalogCategoryPrepareSave(Varien_Event_Observer $observer) 
    { 
     $phpDefaultMaxInputVars = (int)ini_get('max_input_vars'); 
     /** @var Mage_Core_Controller_Request_Http $request */ 
     $request = $observer->getRequest(); 
     $dataProducts = $request->getPost('category_products'); 
     $dataProducts = preg_split('/&/', $dataProducts, -1, PREG_SPLIT_NO_EMPTY); 
     /** @var Mage_Catalog_Model_Category $category */ 
     $category = $observer->getCategory(); 

     if ($dataProducts && !$category->getProductsReadonly() && count($dataProducts) > $phpDefaultMaxInputVars) { 
      $products = array(); 
      foreach ($dataProducts as $_product) { 
       $_product = trim($_product); 
       if (preg_match('/([0-9]*)=([\-]?[0-9]*)/', $_product, $matches)) { 
        $products[$matches[1]] = $matches[2]; 
       } 
      } 
      $category->setPostedProducts($products); 
     } 
    } 
} 

(Source)

0

Giải pháp 2 từ programmeurweb bị lỗi, trên Magento 1.8.0.0!

if (!empty($k) && !empty($v)) { 
    $products[$k] = $v; 
} 

Nó nên là:

if (!empty($k)) { 
    $products[$k] = $v; 
} 

$ v được sử dụng cho 'vị trí' và không phải là một giá trị checkbox = 1 (là sản phẩm kết hợp với hộp kiểm loại hiện hành).

Tôi đã thử nghiệm điều này rồi. Tôi có sai không?

Điều này nhắc nhở đừng bao giờ sao chép & dán mã từ mạng.

PS: Tôi không thể nhận xét câu trả lời ngay bây giờ.

Các vấn đề liên quan