3

当我在 Magento 中以非常大$sku的 执行以下语句时,执行终止而不会抛出任何错误。Magento、Apache 或 PHP 的错误日志中都没有错误。

Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);

问题:如何捕获错误?

我尝试设置自定义错误处理程序,并且出于测试目的,我还设法触发了调用每个错误处理程序函数的错误情况。但是当运行前面提到的带有大的 Magento 代码时$sku,不会执行任何错误处理函数。

error_reporting( -1 );
set_error_handler( array( 'Error', 'captureNormal' ) );
set_exception_handler( array( 'Error', 'captureException' ) );
register_shutdown_function( array( 'Error', 'captureShutdown' ) );

为了完整起见,这是$sku我传递给loadByAttribute(). (sku 无效,但这不是问题)

1- 9685 0102046 | 1- 9685 1212100 | 1- 9685 1212092 | 1- 9685 1212096 | 1- 9685 1102100 | 1- 9685 1102108 | 1- 9685 1- 9685 0102056|1- 9685 0102058|1- 9685 1212104|1- 9685 1212108|1- 9685 0212058|1- 9685 0104050|1- 9685 0212050|1- 9685 0212056|1- 9685 0212044|1- 9685 0212048| 1- 9685 0212052|1- 9685 0212054|1- 9685 1102104|1- 9685 1102124

非常感谢您对此事的任何见解!

更新:经过进一步调查,这是代码中执行终止的确切点。当执行 foreach 时,我猜 Magento 进入 MySQL 世界并开始从数据库加载数据。

\Mage\Catalog\Model\Abstract.php

 public function loadByAttribute($attribute, $value, $additionalAttributes = '*')
    {
        $collection = $this->getResourceCollection()
            ->addAttributeToSelect($additionalAttributes)
            ->addAttributeToFilter($attribute, $value)
            ->setPage(1,1);

        foreach ($collection as $object) { // <--------------- HERE
            return $object;
        }
        return false;
    }

请注意,我只对找出如何正确捕获这些类型的错误感兴趣,而不是“修复”逻辑。这样我就可以向用户显示正确的错误消息。上面带有畸形 sku 的示例是人为的,我不想让我的 Magento 应用程序与那些错误的 sku 一起工作。

更新:错误原因

我跟踪了load()由 触发的调用,foreach它归结为一个错误 Zend / PHP。

我追踪了对 \www\lib\Zend\Db\Statement.php 的调用_stripQuoted($sql),以及以下语句:( $sql = preg_replace("/$q($qe|\\\\{2}|[^$q])*$q/", '', $sql);在 Magento 1.7.0.2 的第 204 行)。

preg_replace使用该语句生成的 SQL 运行时load(),程序就终止了。apache 或 php 的日志中都没有任何痕迹。日志有效,因为它们充满了其他东西。

我在这个问题上找到了这个错误报告。他们在那里表明这是一个分段错误。我想没有办法从中恢复(?)。

由于问题明确是关于如何捕获错误条件,而且这里的许多建议更多是关于清理数据,我认为赏金没有明确的“赢家”。但 Franklin P Strube 至少暗示要在筹码更深的地方过牌,所以他明白了。

谢谢你们所有的帮助。如果您对如何处理段错误有任何建议,请分享 =)。

4

8 回答 8

1

我相信脚本在堆栈中的终止可能比您指出的更深。当一个集合开始“foreach”循环时,它必须首先调用“load”函数,该函数专门用于构建 SQL。

您可以尝试记录Mage::log((string)$collection->getSelect());以查看 SQL 查询是否有问题。

或者,您是否能够在过滤之前对 sku 进行消毒?也许使用观察者?

于 2012-10-16T02:07:59.767 回答
0

不要忘记在 php.ini、.htaccess 或使用 ini_set 中设置日志路径。

.htaccess 示例:

php_flag log_errors on
php_value error_log /var/www/PHP_errors.log

.

如果 Magento 正在使用 PDO,通常应该将 PDO 设置为异常模式。

这是我在 PHP 5.2.x 中使用的:

error_reporting(-1);
ini_set("display_errors", "On");

function errhandler($nSeverity, $strMessage, $strFilePath, $nLineNumber){
    error_log(PHP_EOL.date("Y-m-d H:m:s", time())." ".$strFilePath."#".$nLineNumber.": ".$strMessage.PHP_EOL);
    throw new ErrorException($strMessage, /*nExceptionCode*/ 0, $nSeverity, $strFilePath, $nLineNumber);
}
set_error_handler("errhandler", -1);
于 2012-10-28T21:40:02.627 回答
0

当 PHP 内存不足时会出现此问题,

从 php.ini 增加允许的内存大小或增加内存限制,

把这个ini_set('memory_limit', '512M');

于 2012-10-30T12:33:35.157 回答
0

我不认为这是foreach杀死脚本的原因。

尝试在之前立即拆卸呼叫:

public function loadByAttribute($attribute, $value, $additionalAttributes = '*')
{
    $res1 = $this->getResourceCollection();
    $res2 = $res1->addAttributeToSelect($additionalAttributes);
    $res3 = $res2->addAttributeToFilter($attribute, $value);

    $collection = $res3->setPage(1,1);

    foreach ($collection as $object)
        return $object;
    }
    return false;
}

否则,如果 SKU 长度过长,或者 SKU 未通过某些清理检查,您可能只想简单地引发异常。

于 2012-11-02T22:15:07.647 回答
0

在 index.php 中,将以下行移动到 index.php 文件的顶部:

ini_set('display_errors', 1);

由于权限问题,我感觉您的问题没有标记此触发器。我运行这两个命令以确保在文件/目录上正确设置权限。

find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
于 2012-10-30T14:23:57.120 回答
0

您不需要注册自己的错误处理程序,Magento 已经为您完成了。您需要做的只是几个步骤:

  1. 通过取消注释 index.php 中的下一行来打开错误报告:

    #ini_set('display_errors', 1);
    
  2. 确保日志记录已打开:转到管理面板系统->配置->开发人员->日志设置,将启用设置为是。现在您可以var/log从 Magento 根目录检查 Magento 登录。

任何 php 错误都应属于 php Fatal Error 或日志。

于 2012-10-15T11:58:08.647 回答
0

前两个问题:

  • 你怎么知道实际上有错误?例如,在 php 代码的exit某些部分中,不会引发错误,但脚本将被终止。
  • 你说"I guess Magento goes into MySQL world and starts loading up data from the database"。你检查过你的 MySQL 服务器上发生了什么吗?SQL 查询真的被发送了吗?如果它被发送,它是否被处理、出错或停止?

我建议使用调试器从foreach ( $collection行开始逐步执​​行 PHP 代码。我不知道您使用的是什么编辑器/IDE,您可以设置NetbeansXDebug以允许设置断点和单步执行代码。

于 2012-11-02T16:47:18.517 回答
0

Magento 1.7 中的客户也有同样的错误。

我有一个 sql insert 语句,它将侧边栏购物车 html 保存在一个字段中,并且在该语句中我使用了该 html 的 addlashes。

当该 html 中有 1 到 5 个产品时,save 语句将成功执行。

当产品超过 5 个时,这意味着 html 较长但每个产品的部分相同,我也在此错误中运行。

程序停在 $sql = preg_replace("/$q($qe|\\{2}|[^$q])*$q/", '', $sql); 并且看不到任何错误。

这似乎是一个内存问题,有 6 个产品我超过了大小限制(现在是 7000 个字符),所以我猜提供商必须更改 php 设置..

于 2014-10-01T23:35:57.873 回答