使用Magento的后台,在保存链接到许多产品的类别后,仅保留前1000个产品(或2000个或x000,取决于主机配置(。
所有其他类别/产品链接将从数据库的catalog_category_product
表中删除。
即使产品网格(类别产品选项卡(中未取消选中任何复选框,也会发生这种情况。
不显示或记录任何错误消息。
跟踪从浏览器发布到服务器的数据不会显示任何丢失的产品 ID,但即使您在后台网格上检查更多产品,在最终保存类别时,服务器也只保留第一个 x000 并删除其他 ID...
虽然可以在其他网站上找到一些答案,但我认为值得在 StackOverflow 上分享这个......
问题的根源可以在Mage_Adminhtml_Catalog_CategoryController
中找到,其中saveAction()
方法检索一个大的POSTed字符串(category_products
,像查询字符串一样编码(,由PHP函数parse_str()
处理:
if (isset($data['category_products']) && !$category->getProductsReadonly()) {
$products = array();
parse_str($data['category_products'], $products);
$category->setPostedProducts($products);
}
唉!从 PHP 的 5.3.9 版开始,有一个名为 max_input_vars
的新配置设置,它限制了可以接受的输入变量的数量。
这个极限主要适用于$_GET
、$_POST
和$_COOKIE
超全局变量,但也由parse_str()
函数内部使用!
(参见 PHP 手册(
因此,根据主机的php.ini
配置,链接到类别的产品数量受此设置的限制...
一种解决方案是增加max_input_vars
的值,以php.ini
或.htaccess
为单位:
<IfModule mod_php5.c>
php_value max_input_vars 10000
</IfModule>
甚至可以通过仅针对管理页面更改此设置来更安全地完成此操作(使 LocationMatch 模式适应您自己的后台 URL 样式(:
<LocationMatch "mymagentostore/(index'.php/)?admin/">
<IfModule mod_php5.c>
php_value max_input_vars 10000
</IfModule>
</LocationMatch>
(来源(
这只能解决问题,直到您的一个类别达到新的最大产品数量......
另一种解决方案是修复Magento的代码,以便在此时不使用parse_str((函数。
例如,在 Mage_Adminhtml_Catalog_CategoryController
中,saveAction()
方法替换:
parse_str($data['category_products'], $products);
跟:
$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;
}
}
(来源(
很难决定哪种解决方案是最好的,因为第一个解决方案使您的服务器更容易受到攻击(因为max_input_vars
旨在减轻使用哈希冲突的拒绝服务攻击的可能性(,而第二个解决方案使您修改Magento核心类,这可能会导致将来Magento升级中的进一步问题...
希望这无论如何都是有用的,在我找到为什么某些类别不断丢失某些产品之前,我挣扎了一段时间!
最好的解决方案是使用观察者事件"catalog_category_prepare_save"。所以你需要改变你的模块的配置.xml:
<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>
然后将函数添加到应用程序/代码/本地/您的/模块/模型/观察者.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);
}
}
}
(来源(
我找到了一个可行的解决方案,所以我在这里分享它!
在magento root
文件夹中创建一个文件名php5.ini
,并在第一行中放置此代码
[PHP]
max_input_vars = 5000
现在,如果它不起作用,则需要在服务器PHP,ini(/usr/local/lib/php.ini(中添加此行
max_input_vars = 5000
希望它有帮助。
<IfModule mod_php5.c>
php_value max_input_vars 10000
</IfModule>
为我做了这个技巧,我遇到了与上述相同的问题,Magento 1.4.1.1 仅在该类别中保存了 1001 种产品,但是将上面的代码放入我的 .htaccess 后,错误消失了。
来自 programmeurweb 的解决方案 2 在 Magento 1.8.0.0 上被窃听!
if (!empty($k) && !empty($v)) {
$products[$k] = $v;
}
它应该是:
if (!empty($k)) {
$products[$k] = $v;
}
$v用于"位置",而不是复选框值 = 1(作为将产品关联到当前类别复选框(。
我已经测试过了。我错了吗?
这让人想起永远不要从网络复制和粘贴代码。
PS:我现在无法评论答案。
LocationMatch 在 .htaccess 中是不允许的,它只能放在 Apache httpd.conf 中
首选方法是创建一个 Apache 包含,而不是直接修改 httpd.conf,因为它会在下次更新/重建时中断。
就我而言,我创建了一个包含文件pre_virtualhost_global.conf并将以下代码放入其中:
<LocationMatch "mymagentostore/(index'.php/)?admin/">
<IfModule mod_php5.c>
php_value max_input_vars 10000
</IfModule>
之后,当然,您需要重新启动 apache。我使用了我的WebHostManager,所以这是一个简单的过程。
更多信息可以在以下位置找到:
[http://docs.cpanel.net/twiki/bin/view/EasyApache3/WebHome#Custom http.conf指令][1]
我认为这是最优雅的解决方案,不接触Magento Core,适用于服务器上的所有站点,还可以保护前端。
[1]: https://web.archive.org/web/20140804033608/http://docs.cpanel.net:80/twiki/bin/view/EasyApache3/WebHome?#Custom http.conf 指令