调试¶
概览¶

PHP 提供了用于调试应用程序的工具,包括通知、警告、错误和异常。The异常类提供了发生错误位置的相关信息,例如文件、行号、消息、数字代码、回溯等。像 Phalcon 这样的 OOP 框架主要使用此类封装此功能,并向开发人员或用户提供信息。
尽管 Phalcon 是用 C 编写的,但它在 PHP 用户空间中执行方法,提供了与其他基于 PHP 的框架相同的调试功能。
异常¶
控制应用程序中(有意或无意)错误流的一种非常常见的方式是使用try/catch块来捕获异常。我们的文档中有许多示例展示了这些块的使用。
在块内抛出的任何异常都会被捕获到变量$ex中。一个Phalcon\Support\Debug\Exception继承了 PHP 的异常类. 使用 Phalcon 异常可以区分异常是由 Phalcon 相关代码抛出还是来自其他地方。
The 异常类,暴露了以下内容:
<?php
class Exception
{
    protected int $code;
    protected string $file;
    protected int $line;
    protected string $message;
    public function __construct(
        string $message = '' 
        [, int $code = 0 
        [, Exception $previous = null ]]]
    );
    public function __toString(): string;
    final public function getCode(): int;
    final public function getFile(): string;
    final public function getLine(): int;
    final public function getMessage(): string;
    final public function getPrevious(): Exception;
    final public function getTrace(): array;
    final public function getTraceAsString(): string;
    final private function __clone(): void;
}
使用Phalcon\Support\Debug\Exception:
<?php
use Phalcon\Support\Debug\Exception;
try {
    // ...
} catch (Exception $ex) {
    echo get_class($ex), ': ', $ex->getMessage(), PHP_EOL;
    echo ' File=', $ex->getFile(), PHP_EOL;
    echo ' Line=', $ex->getLine(), PHP_EOL;
    echo $ex->getTraceAsString();
}
时,可以使用相同的方法调用来查找生成异常的应用程序代码所在的文件和行号,以及涉及生成异常的组件:
PDOException: SQLSTATE[28000] [1045] Access denied for user 'root'@'localhost'
    (using password: NO)
 File=/app/public/index.php
 Line=74
#0 [internal function]: PDO->__construct('mysql:host=loca...', 'root', '', Array)
#1 [internal function]: Phalcon\Db\Adapter\Pdo->connect(Array)
#2 /app/public/index.php(74):
    Phalcon\Db\Adapter\Pdo->__construct(Array)
#3 [internal function]: {closure}()
#4 [internal function]: call_user_func_array(Object(Closure), Array)
#5 [internal function]: Phalcon\Di->_factory(Object(Closure), Array)
#6 [internal function]: Phalcon\Di->get('db', Array)
#7 [internal function]: Phalcon\Di->getShared('db')
#8 [internal function]: Phalcon\Mvc\Model->getConnection()
#9 [internal function]: Phalcon\Mvc\Model::_getOrCreateResultset('Users', Array, true)
#10 /app/app/controllers/SessionController.php(83):
    Phalcon\Mvc\Model::findFirst('email='demo@pha...')
#11 [internal function]: SessionController->startAction()
#12 [internal function]: call_user_func_array(Array, Array)
#13 [internal function]: Phalcon\Mvc\Dispatcher->dispatch()
#14 /app/public/index.php(114): Phalcon\Mvc\Application->handle()
#15 {main}
如上所示,Phalcon 被编译为 PHP 扩展并不重要。异常信息包含生成上述异常片段时所涉及的参数和方法调用。Exception::getTrace()在必要时提供更多信息。
构造函数¶
Phalcon\Support\Debug为开发人员提供视觉辅助和附加信息,以帮助他们轻松定位应用程序中产生的错误。
注意
请确保不要在生产环境中使用此组件,因为它可能会向攻击者透露有关您的服务器的信息。
下面的录屏解释了它是如何工作的:
要启用它,请在引导程序中添加以下内容:
或者使用更简洁的语法:
注意
必须移除或禁用所有try/catch块以使此组件正常工作。
默认情况下,该组件将监听未捕获的异常,但不会监听低严重性错误(警告、通知等)。您可以通过在listen()
exceptions- 布尔值lowSeverity- 布尔值
在下面的示例中,不监听未捕获的异常,但监听非静默的通知或警告(低严重性):
如果您的应用程序流程不同,或者不想在listen()上传递参数,您始终可以使用listenExceptions()和listenLowSeverity():
<?php
use Phalcon\Support\Debug;
$debug = new Debug();
$debug
    ->listenExceptions()
    ->listenLowSeverity()
    ->listen();
注意
The listenExceptions()和listenLowSeverity()是开启开关。如果您希望关闭监听异常或低严重性错误的功能,关闭则需要在false中传递listen()方法设置容器。
获取方法¶
参数。
| 方法 | 返回 | 描述 | 
|---|---|---|
getCssSources() |  string |  返回用于在屏幕上显示内容的样式表 | 
getJsSources() |  string |  返回用于在屏幕上显示内容的 JavaScript 文件 | 
getVersion() |  string |  返回当前版本文档的链接 | 
扩展组件并重写getCssSources()例如返回不同的 CSS HTML 指令,将改变屏幕输出的外观。输出的 CSS 类是基于Bootstrap CSS.
设置器¶
Phalcon\Support\Debug还提供了一些设置器以更好地自定义应用程序发生错误时的输出。
| 方法 | 描述 | 
|---|---|
setShowBackTrace(bool $showBackTrace) |  显示/隐藏异常的回溯 | 
setShowFileFragment(bool $showFileFragment) |  显示/隐藏输出中的文件片段(与异常相关) | 
setShowFiles(bool $showFiles) |  显示/隐藏回溯中的文件 | 
setUri(string $uri) |  静态资源的基本 URI(另见获取器部分以自定义组件) | 
变量¶
您还可以使用debugVar()方法,注入您希望在输出中呈现的任何额外变量。这些通常是特定于应用程序的变量。例如,显示应用程序的计时信息。
<?php
use Phalcon\Support\Debug;
$debug = new Debug();
$time = time();
$debug
    ->debugVar('time', $time)
    ->listen();
要清除变量堆栈,您可以调用clearVars().
最后,通过调用这个方法,您可以停止应用程序的执行并触发显示回溯。halt()
<?php
use Phalcon\Support\Debug;
$debug = new Debug();
$debug->listen();
// .....
if (12345 === $password) {
    $debug->halt();
}
输出黑名单¶
如上所述,该组件不应在生产环境中启用。由于 Phalcon 无法控制此行为,因此有一个内置的黑名单功能,允许开发人员屏蔽他们不希望在屏幕上显示的某些信息,以防万一。这些都是$_REQUEST和$_SERVER数组的元素。
<?php
use Phalcon\Support\Debug;
$debug = new Debug();
$debug
    ->setBlacklist(
        [
            'request' => ['some'],
            'server'  => ['hostname'],
        ]
    )
    ->listen();
在上面的示例中,我们将永远不会显示some元素$_REQUEST来自hostname来自$_SERVER。您可以随时添加更多不需要显示的元素,这些元素存在于这两个超级全局数组中。这在您忘记在生产环境中禁用该组件时特别有用。让它保持启用状态是不良实践,但如果忘记了,至少主机的一些关键信息不会被潜在黑客看到。
注意
要隐藏的数组元素的键区分大小写
处理程序¶
为了捕获异常和低严重性错误,Phalcon\Support\Debug使用了onUncaughtException()和onUncaughtLowSeverity()。大多数使用此组件的开发者永远不需要扩展这些方法。但是,如果您希望这样做,可以通过扩展组件并重写这些方法来操作异常并返回所需的输出。
这两种方法正被设置为异常处理程序,使用 PHP 的set_exception_handler。当调用listenExceptions()超全局变量。如果cookie存在于任一集合中,则返回onUncaughtException()注册时,而当调用listenLowSeverity()超全局变量。如果cookie存在于任一集合中,则返回onUncaughtLowSeverity注册时。
反射与内省¶
Phalcon 类与其他 PHP 类并无不同,因此你可以使用Reflection API或者简单地打印任何对象以显示其内容和状态:
上面的例子输出以下内容:
Phalcon\Mvc\Router Object
(
    [_dependencyInjector:protected] =>
    [_module:protected] =>
    [_controller:protected] =>
    [_action:protected] =>
    [_params:protected] => Array
        (
        )
    [_routes:protected] => Array
        (
            [0] => Phalcon\Mvc\Router\Route Object
                (
                    [_pattern:protected] => #^/([a-zA-Z0-9\_]+)[/]{0,1}$#
                    [_compiledPattern:protected] => #^/([a-zA-Z0-9\_]+)[/]{0,1}$#
                    [_paths:protected] => Array
                        (
                            [controller] => 1
                        )
                    [_methods:protected] =>
                    [_id:protected] => 0
                    [_name:protected] =>
                )
            [1] => Phalcon\Mvc\Router\Route Object
                (
                    [_pattern:protected] => #^/([a-zA-Z0-9\_]+)/([a-zA-Z0-9\_]+)(/.*)*$#
                    [_compiledPattern:protected] => #^/([a-zA-Z0-9\_]+)/([a-zA-Z0-9\_]+)(/.*)*$#
                    [_paths:protected] => Array
                        (
                            [controller] => 1
                            [action] => 2
                            [params] => 3
                        )
                    [_methods:protected] =>
                    [_id:protected] => 1
                    [_name:protected] =>
                )
        )
    [_matchedRoute:protected] =>
    [_matches:protected] =>
    [_wasMatched:protected] =>
    [_defaultModule:protected] =>
    [_defaultController:protected] =>
    [_defaultAction:protected] =>
    [_defaultParams:protected] => Array
        (
        )
)
Xdebug¶
Xdebug是一个令人惊叹的工具,它可以补充 PHP 应用程序的调试功能。它也是一个 PHP 的 C 扩展,你可以将其与 Phalcon 一起使用,而无需额外配置或担心副作用。
安装 Xdebug 后,你可以使用其 API 获取关于异常和消息的更详细信息。
注意
我们强烈建议使用最新版本的 Xdebug 以实现与 Phalcon 更好的兼容性。
下面的例子实现了xdebug_print_function_stack来停止执行并生成回溯信息:
<?php
use Phalcon\Mvc\Controller;
class SignupController extends Controller
{
    public function indexAction()
    {
    }
    public function registerAction()
    {
        $name  = $this->request->getPost('name', 'string');
        $email = $this->request->getPost('email', 'email');
        // Stop execution and show a backtrace
        return xdebug_print_function_stack('stop here!');
        $user        = new Users();
        $user->name  = $name;
        $user->email = $email;
        // Store and check for errors
        $user->save();
    }
}
对于上面的例子,Xdebug 还会向我们展示局部作用域中的变量以及回溯信息:
Xdebug: stop here! in /app/app/controllers/SignupController.php
on line 19
Call Stack:
0.0383     654600   1. {main}() /app//public/index.php:0
0.0392     663864   2. Phalcon\Mvc\Application->handle()
/app/public/index.php:37
0.0418     738848   3. SignupController->registerAction()
/app/public/index.php:0
0.0419     740144   4. xdebug_print_function_stack()
/app/app/controllers/SignupController.php:19
Xdebug 提供了多种方式来获取有关使用 Phalcon 执行应用程序的调试和跟踪信息。你可以查阅XDebug 文档以获取更多信息。
要为 PHPStorm 设置 Xdebug,你可以参考这篇文章。