解決magento批量assign產品到分類時最多隻能save成功1000件的問題
注 :文章中問題已在Magento EE 1.14 / CE 1.9得到驗證。
最近,我發現了一件非常奇怪的問題。當為一批產品(大於1000件)分配分類時,只有最多一千件產品能夠儲存成功,而其他的都被忽略了。為了解決這個問題,就需要我們去深入magento的原始碼進行分析測試。
下面是Magento如何分配產品類別的原始碼:
class Mage_Adminhtml_Catalog_CategoryController extends Mage_Adminhtml_Controller_Action { public function saveAction() { . . . if (isset($data['category_products']) && !$category->getProductsReadonly()) { $products = array(); parse_str($data['category_products'], $products); $category->setPostedProducts($products); } . . . } }
$data[‘category_products’]是一個產品序列的字串,通過parse_str生成一個關聯陣列將產品儲存的一個數組中。但是但從這段程式碼,並沒有看出哪裡不對,再去error log裡檢查下,於是發現有如下的警告:
Warning: parse_str(): Input variables exceeded 1000. To increase the limit change
max_input_vars in php.ini.
如你所看到的,這個問題是由於PHP的配置引數max_input_vars引起的,因為php限制了可以接受的輸入變數的數量。在PHP版本5.3.9 的說明裡有介紹,大致是為了避免雜湊衝突, Parse_str對引數數量進行了限制。結果陣列的長度大於或者等於1000時,預設只取1000個,這就是為什麼只有一個千的產品得到了儲存,其餘則沒有。
要解決這個問題,有2個辦法。一是增加max_input_vars引數的值,二是修改magento程式碼。
1:修改Max_input_vars的值
Max_input_vars值又可以通過兩種方式來改變,修改htaccess或修改php.ini。
在magento根目錄的htaccess裡新增如下行,數值可以視情況改變:
php_value max_input_vars 2000
找到php.ini,找到max_input_vars = 1000,如果改行被註釋,就取消註釋,然後調整數值。為了使更 改生效,你可能需要重新啟動伺服器。
2:修改magento程式碼
改變max_input_vars值雖然快速且簡單。但是,如果你的產品和類別每天都在飛速增長著,這種重複 操作就顯得有點麻煩。為了避免這種情況,我們可以試著像下面來修改程式碼:
require_once 'Mage/Adminhtml/controllers/Catalog/CategoryController.php';
class Inchoo_Smile_Adminhtml_Catalog_CategoryController extends
Mage_Adminhtml_Catalog_CategoryController
{
public function saveAction()
{
...
if (isset($data['category_products']) && !$category->getProductsReadonly()) {
$products = array();
$exploded = explode('&', $data['category_products']);
foreach ($exploded as $row) {
$temp = array();
parse_str($row, $temp);
list($key, $value) = each($temp);
if(!empty($key)) {
$products[$key] = $value;
}
}
$category->setPostedProducts($products);
}
...
}
}
Mage_Adminhtml_Catalog_CategoryController裡,在saveAction的時候,magento會出發一個event叫 catalog_category_prepare_save,通過這個事件就可以對資料進行修改,程式碼如下:
class Inchoo_Smile_Model_Observer
{
// event: catalog_category_prepare_save
public function assignCategoryProducts($observer)
{
$category = $observer->getCategory();
$request = $observer->getRequest();
$products = array();
$exploded = explode('&', $request->getParam('category_products'));
foreach ($exploded as $row) {
$temp = array();
parse_str($row, $temp);
list($key, $value) = each($temp);
if(!empty($key)) {
$products[$key] = $value;
}
}
$category->setPostedProducts($products);
}
}
以上程式碼可以放入任何一個你自己寫的module裡,然後再config里加上event即可,記著不要去修改 magento的核心程式碼。
來自於:jonas的magento部落格