Magento 对未定义对象的 count() 分层导航调用
Magento Layered navigation call to count() on undefined object
我在分层导航块中遇到了一个问题,我认为这可能是一个错误。
在块 Mage_Catalog_Block_Navigation 中,方法 _renderCategoryMenuItemHtml:
// get all children
// If Flat Data enabled then use it but only on frontend
$flatHelper = Mage::helper('catalog/category_flat');
if ($flatHelper->isAvailable() && $flatHelper->isBuilt(true) && !Mage::app()->getStore()->isAdmin()) {
$children = (array)$category->getChildrenNodes();
$childrenCount = count($children);
} else {
$children = $category->getChildren();
$childrenCount = $children->count();
}
我启用了平面类别索引,并且在计划时(每分钟)重建索引。 Magento 版本是 1.14.0.1,有时我会收到一条错误消息:
Call to a member function count() on a non-object
基于 if 子句,我假设当有人在重建索引 (isAvailable) 时访问页面时会发生这种情况。
问题是 else 块中的代码似乎甚至在理论上都不起作用,因为 $category->getChildren() returns 一个字符串。我在这里错过了什么吗?这是一个错误还是我在某处配置错误。
您可以通过打开缓存(所有 cms/catalog/category/404 页面都是在企业版中缓存的完整页面)并在重建索引完成后定期刷新缓存来避免这种情况。考虑增加重建索引之间的间隔。
如果使用内置设置进行调整不起作用,您可以随时进行调试:
Create a log file and make it writable
touch mage-root/var/log/counts.log
chmod 755 mage-root/var/log/counts.log
Replace the child calls with:
// get all children
// If Flat Data enabled then use it but only on frontend
$flatHelper = Mage::helper('catalog/category_flat');
Mage::log( 'Flat data enabled: ' . $flatHelper, null, 'counts.log', FALSE );
if ($flatHelper->isAvailable() && $flatHelper->isBuilt(true) && !Mage::app()->getStore()->isAdmin()) {
$children = (array)$category->getChildrenNodes();
Mage::log( 'Children in if: ' . $children, null, 'counts.log', FALSE );
$childrenCount = count($children);
} else {
$children = $category->getChildren();
Mage::log( 'Children in else: ' . $children, null, 'counts.log', FALSE );
$childrenCount = $children->count();
}
最后,您可以通过将原版 class 复制到以下位置来覆盖它:
app\code\local\Mage\Catalog\Block\Navigation.php
然后在违规语句上方添加 if( !empty( $children ) )
并长期使用此 'patch'。
进一步查看后,它看起来像是一个错误。问题是竞争条件:
- Mage_Catalog_Model_Category::_construct 决定使用什么,EAV 或 Flat 资源
- 然后 Mage_Catalog_Helper_Category::getStoreCategories returns 基于此的不同集合。
- 在 Mage_Catalog_Block_Navigation::_renderCategoryMenuItemHtml 中,$category 对象是 Mage_Catalog_Model_Category 或 Varien_Data_Tree_Node 基于之前使用 Flat 或 EAV 的决定。
- Mage_Catalog_Block_Navigation::_renderCategoryMenuItemHtml 再次检查是否将对象视为 Flat 或 EAV,并根据此调用不同的方法。
因此,在使用 Flat 资源初始化类别的情况下,类别索引过程在最后一个方法之后但之前的某个时间被锁定,Magento 将处理 $category 作为错误类型的对象。
我的解决方案是另外检查 else 部分中的 $category 类型。
} else {
if( $category instanceof Varien_Data_Tree_Node )
{
$children = $category->getChildren();
} else
{
$children = $category->getChildrenCategories();
}
}
我有点害怕的是一个问题,因为我在锁定时访问类别索引。
我在分层导航块中遇到了一个问题,我认为这可能是一个错误。
在块 Mage_Catalog_Block_Navigation 中,方法 _renderCategoryMenuItemHtml:
// get all children
// If Flat Data enabled then use it but only on frontend
$flatHelper = Mage::helper('catalog/category_flat');
if ($flatHelper->isAvailable() && $flatHelper->isBuilt(true) && !Mage::app()->getStore()->isAdmin()) {
$children = (array)$category->getChildrenNodes();
$childrenCount = count($children);
} else {
$children = $category->getChildren();
$childrenCount = $children->count();
}
我启用了平面类别索引,并且在计划时(每分钟)重建索引。 Magento 版本是 1.14.0.1,有时我会收到一条错误消息:
Call to a member function count() on a non-object
基于 if 子句,我假设当有人在重建索引 (isAvailable) 时访问页面时会发生这种情况。
问题是 else 块中的代码似乎甚至在理论上都不起作用,因为 $category->getChildren() returns 一个字符串。我在这里错过了什么吗?这是一个错误还是我在某处配置错误。
您可以通过打开缓存(所有 cms/catalog/category/404 页面都是在企业版中缓存的完整页面)并在重建索引完成后定期刷新缓存来避免这种情况。考虑增加重建索引之间的间隔。
如果使用内置设置进行调整不起作用,您可以随时进行调试:
Create a log file and make it writable
touch mage-root/var/log/counts.log
chmod 755 mage-root/var/log/counts.log
Replace the child calls with:
// get all children
// If Flat Data enabled then use it but only on frontend
$flatHelper = Mage::helper('catalog/category_flat');
Mage::log( 'Flat data enabled: ' . $flatHelper, null, 'counts.log', FALSE );
if ($flatHelper->isAvailable() && $flatHelper->isBuilt(true) && !Mage::app()->getStore()->isAdmin()) {
$children = (array)$category->getChildrenNodes();
Mage::log( 'Children in if: ' . $children, null, 'counts.log', FALSE );
$childrenCount = count($children);
} else {
$children = $category->getChildren();
Mage::log( 'Children in else: ' . $children, null, 'counts.log', FALSE );
$childrenCount = $children->count();
}
最后,您可以通过将原版 class 复制到以下位置来覆盖它:
app\code\local\Mage\Catalog\Block\Navigation.php
然后在违规语句上方添加 if( !empty( $children ) )
并长期使用此 'patch'。
进一步查看后,它看起来像是一个错误。问题是竞争条件:
- Mage_Catalog_Model_Category::_construct 决定使用什么,EAV 或 Flat 资源
- 然后 Mage_Catalog_Helper_Category::getStoreCategories returns 基于此的不同集合。
- 在 Mage_Catalog_Block_Navigation::_renderCategoryMenuItemHtml 中,$category 对象是 Mage_Catalog_Model_Category 或 Varien_Data_Tree_Node 基于之前使用 Flat 或 EAV 的决定。
- Mage_Catalog_Block_Navigation::_renderCategoryMenuItemHtml 再次检查是否将对象视为 Flat 或 EAV,并根据此调用不同的方法。
因此,在使用 Flat 资源初始化类别的情况下,类别索引过程在最后一个方法之后但之前的某个时间被锁定,Magento 将处理 $category 作为错误类型的对象。
我的解决方案是另外检查 else 部分中的 $category 类型。
} else {
if( $category instanceof Varien_Data_Tree_Node )
{
$children = $category->getChildren();
} else
{
$children = $category->getChildrenCategories();
}
}
我有点害怕的是一个问题,因为我在锁定时访问类别索引。