PHP/Laravel中的“异常链”

之前知道,Python 3 中终于实现了对异常链的支持。 最近,在代码中,有一处写着:

try {
// some code
} catch (\Exception $e) {
\Log::error(‘xxx_id’ . $xxx->id);
}

问了之后才发现,这是需要知道是哪个id触发的错误,如果不捕获异常的话,在backtrace信息中可能不会出现此id。 但是,这样做虽然可以达到他的目的,但是掩盖了底层的错误,对后续的追查不利。 然后,作为(伪)Python开发者的我就想起了Python3中的异常链技术,所以找了下PHP中有没有类似的东西,结果发现:自PHP 5.3开始,支持了类似的技术。 解决方案:可以自己扩展Excepiton类,默认的构造方法里面,第三个参数是前一个异常,经过测试,在Laravel框架中,同一条链中的Exception都会展示出来(无论是在Console输出,还是日志输出中)。


好,让我们来自己试一试。 首先写一个Command:

class NestExceptionTest extends Command
{
protected $name = ‘NestExceptionTest’;

public function fire()
{
    try {
        $this->testOneLevel();
    } catch (\\Exception $e) {
        throw new \\Exception("top level", 0, $e);
    }
}

private function testOneLevel()
{
    try {
        $this->testTwoLeve();
    } catch (\\Exception $e) {
        throw new \\Exception('one level', 0, $e);
    }
}

private function testTwoLeve()
{
    throw new \\Exception('two level');
}

}

为了偷懒,就没有自己定义自己的Exception,仅仅是不同的错误信息来区分。 执行此命令,输出如下: Exception output console同时,日志输出如下:

[2015-12-12 13:54:06] production.ERROR: exception ‘Exception’ with message ‘two level’ in /Users/robberphex/projects/xxx/app/Console/Commands/NestExceptionTest.job:31
Stack trace:
#0 /Users/robberphex/projects/xxx/app/Console/Commands/NestExceptionTest.job(23): App\Console\Commands\SiteMap\SiteMapBuild->testTwoLeve()
#1 /Users/robberphex/projects/xxx/app/Console/Commands/NestExceptionTest.job(14): App\Console\Commands\SiteMap\SiteMapBuild->testOneLevel()
#2 [internal function]: App\Console\Commands\SiteMap\SiteMapBuild->fire()
#3 /Users/robberphex/projects/xxx/vendor/laravel/framework/src/Illuminate/Container/Container.php(503): call_user_func_array(Array, Array)
#4 /Users/robberphex/projects/xxx/vendor/laravel/framework/src/Illuminate/Console/Command.php(150): Illuminate\Container\Container->call(Array)
#5 /Users/robberphex/projects/xxx/vendor/symfony/console/Command/Command.php(256): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /Users/robberphex/projects/xxx/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /Users/robberphex/projects/xxx/vendor/symfony/console/Application.php(838): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /Users/robberphex/projects/xxx/vendor/symfony/console/Application.php(189): Symfony\Component\Console\Application->doRunCommand(Object(App\Console\Commands\SiteMap\SiteMapBuild), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /Users/robberphex/projects/xxx/vendor/symfony/console/Application.php(120): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /Users/robberphex/projects/xxx/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(107): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#11 /Users/robberphex/projects/xxx/artisan(36): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#12 {main}

阅读更多

建立xdebug+eclipse的调试环境

几周了,终于让 eclipse 能够调试php代码了,期间找了许多资料,但是总不能如愿,于是记录如下。

安装xdebug

fedora 下直接安装 php-pecl-xdebug 包就算是配置好了 php 的 xdebug 扩展。

记得systemctl reload httpd.service 访问 phpinfo 页面时应该有 xdebug 的相关信息:

Screenshot from 2013-04-03 16:01:51

然后打开 display_errors ,即 php.ini 里面有 display_errors= On ,那么打开一个有异常的页面会出现彩色提示。

Screenshot from 2013-04-03 15:51:52

配置远程调试

这时可以配置远程调试。在 /etc/php.d/xdebug.ini 中写入如下几行:

1
2
3
4
5
[Xdebug]
xdebug.remote_autostart=On
xdebug.remote_enable=On
xdebug.remote_host=127.0.0.1
xdebug.remote_handler=dbgp
阅读更多