我有一个mysqli调用(
$result = $this->mysqli->query($query)
),其中$query
是一个生成错误的插入语句:“重复条目'dt'键'username_UNIQUE'”;。 我已经设置了 mysqli 报告模式
\mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
此时的调用堆栈大约有 8 个方法深,并且沿途有几个 try-catch 块。
最后,index.php 中有一个 try-catch 块,即最外层的代码块。该异常似乎忽略了所有较深的 try-catch 块,但在最外层的块中被捕获。不确定这是否重要,但除了 index.php 中的代码之外,所有代码块都在类方法中。
为了演示这个问题,我将向您展示index.php 和从index.php 调用的第一个方法。
<?php
define('DS',DIRECTORY_SEPARATOR);
define('APP_START',microtime(true));
define('ROOT_DIR',dirname(__FILE__).DS);
define('FW_DIR',sprintf("%svendor%sfw%s",ROOT_DIR,DS,DS));
define('APP_DIR',sprintf( '%sapp%s',ROOT_DIR,DS));
try {
// set up the autoloader
require sprintf('%sbootstrap%sbootstrap.php',FW_DIR,DS);
// next, set up the factory for all future class instantiation
$factory = new fw\factory\ClassFactory();
// create the app
$app = $factory->getClass('app\app');
// process the request
$ob = "";
$result = $app->go();
// return anything in the output buffer then the application output
echo $ob.$result;
} catch (Exception $e) {
die("Caught Exception in index.php: ".$e->getMessage());
}
我确定上面的代码执行到
$app->go()
,但没有到达echo $ob.$result;
行。
现在这是 $app 类:
<?php
namespace app;
class App extends \fw\app\App
{
protected $trace = false;
public function __construct(protected \fw\exception\ErrorHandler $errorhandler,
protected \fw\session\WebSession $session,
protected \app\http\RequestHandler $requesthandler,
protected \database\MySqlDB $db
) {
parent::__construct();
}
public function go(){
try {
$this->requesthandler->init($this->errorhandler,$this->session,$this->db);
$result = $this->requesthandler->processrequest(false);
} catch (Exception $e) {
die(__METHOD__." : ".$e->__toString());
}
return $result;
}
}
我确定代码输入了
$this->requesthandler->processrequest(false);
。 许多方法调用更深,它到达触发异常的插入语句。
上面的输出是“在index.php中捕获异常:键'username_UNIQUE'的重复条目'dt'”,这显然来自index.php中的catch。我的问题是,为什么代码没有死在 $app 类的 catch 块中(或堆栈中更深的任何其他 try-catch)。
您的
App
班级被指定使用
namespace app;
这意味着将在其中查找引用的类
namespace
。因此,你的
try {
//some code
} catch (Exception $e) {
//some code
}
将捕获
Exception
命名空间内的任何 app
对象,即任何可能抛出的 \app\Exception
。引发的实际异常是 \Exception
的实例,因此它不会被您拥有的 catch
捕获。你可以有
} catch (\Exception $e) {
例如,这是您想要捕获其实例的
Exception
类的完整命名空间名称。