调试应用程序Debugging Applications

../_images/xdebug-1.jpg

Phalcon中提供了提供了几种调试级别即通知,错误和异常。 异常类 Exception class 提供了错误发生时的一些常用的调试信息如文件,行,消息,错误代码,跟踪信息等。 Phalcon主要使用这个异常类来包装这些功能,以方便开发者或用户使用。

PHP offers tools to debug applications with notices, warnings, errors and exceptions. The Exception class offers information such as the file, line, message, numeric code, backtrace etc. on where an error occurred. OOP frameworks like Phalcon mainly use this class to encapsulate this functionality and provide information back to the developer or user.

尽管Phalcon是使用C语言书写的,但其依然如其它的PHP框架般提供了一些必须的调试工具,PHP本身提供的调试工具亦然可以正常使用。

Despite being written in C, Phalcon executes methods in the PHP userland, providing the debug capability that any other application or framework written in PHP has.

捕获异常Catching Exceptions

纵观Phalcon的文档及其提供的例子程序, 有一个最直接的捕获异常的方法即是使用try/catch块:

Throughout the tutorials and examples of the Phalcon documentation, there is a common element that is catching exceptions. This is a try/catch block:

  1. <?php
  2. try {
  3. //... some phalcon/php code
  4. } catch(\Exception $e) {
  5. }

try/catch块内发生的异常会被捕获然后放入 $e 变量。 开发者可以使用 Phalcon\Exception (扩展自 Exception class )来确定异常信息是来自Phalcon还是PHP本身。 PHP产生的所有异常都是基于 Exception class , 且至少含有如下元素:

Any exception thrown within the block is captured in the variable $e. A Phalcon\Exception extends the PHP Exception class and is used to understand whether the exception came from Phalcon or PHP itself.

All exceptions generated by PHP are based on the Exception class, and have at least the following elements:

  1. <?php
  2. class Exception
  3. {
  4. /* Properties */
  5. protected string $message;
  6. protected int $code;
  7. protected string $file;
  8. protected int $line;
  9. /* Methods */
  10. public __construct ([ string $message = "" [, int $code = 0 [, Exception $previous = NULL ]]])
  11. final public string getMessage ( void )
  12. final public Exception getPrevious ( void )
  13. final public mixed getCode ( void )
  14. final public string getFile ( void )
  15. final public int getLine ( void )
  16. final public array getTrace ( void )
  17. final public string getTraceAsString ( void )
  18. public string __toString ( void )
  19. final private void __clone ( void )
  20. }

如从 Exception class 中取得异常信息一样, 我也可以从 PhalconException 中取异常信息。

Retrieving information from Phalcon\Exception is the same as PHP’s Exception class:

  1. <?php
  2. try {
  3. //... app code ...
  4. } catch(\Exception $e) {
  5. echo get_class($e), ": ", $e->getMessage(), "\n";
  6. echo " File=", $e->getFile(), "\n";
  7. echo " Line=", $e->getLine(), "\n";
  8. echo $e->getTraceAsString();
  9. }

因此容易找到生成的异常的文件和应用程序的代码,以及所涉及的组件:

It’s therefore easy to find which file and line of the application’s code generated the exception, as well as the components involved in generating the exception:

  1. PDOException: SQLSTATE[28000] [1045] Access denied for user 'root'@'localhost'
  2. (using password: NO)
  3. File=/Applications/MAMP/htdocs/invo/public/index.php
  4. Line=74
  5. #0 [internal function]: PDO->__construct('mysql:host=loca...', 'root', '', Array)
  6. #1 [internal function]: Phalcon\Db\Adapter\Pdo->connect(Array)
  7. #2 /Applications/MAMP/htdocs/invo/public/index.php(74):
  8. Phalcon\Db\Adapter\Pdo->__construct(Array)
  9. #3 [internal function]: {closure}()
  10. #4 [internal function]: call_user_func_array(Object(Closure), Array)
  11. #5 [internal function]: Phalcon\DI->_factory(Object(Closure), Array)
  12. #6 [internal function]: Phalcon\DI->get('db', Array)
  13. #7 [internal function]: Phalcon\DI->getShared('db')
  14. #8 [internal function]: Phalcon\Mvc\Model->getConnection()
  15. #9 [internal function]: Phalcon\Mvc\Model::_getOrCreateResultset('Users', Array, true)
  16. #10 /Applications/MAMP/htdocs/invo/app/controllers/SessionController.php(83):
  17. Phalcon\Mvc\Model::findFirst('email='demo@pha...')
  18. #11 [internal function]: SessionController->startAction()
  19. #12 [internal function]: call_user_func_array(Array, Array)
  20. #13 [internal function]: Phalcon\Mvc\Dispatcher->dispatch()
  21. #14 /Applications/MAMP/htdocs/invo/public/index.php(114): Phalcon\Mvc\Application->handle()
  22. #15 {main}

从上面我们可以看到异常信息中有Phalcon的类及方法,甚至调用时的参数也显示了出来。 如果需要可以使用 Exception::getTrace 获取更多的信息。

As you can see from the above output the Phalcon’s classes and methods are displayed just like any other component, and even showing the parameters that were invoked in every call. The method Exception::getTrace provides additional information if needed.

调试组件Debug component

Phalcon提供的调试组件可以使开发者更容易的定位代码中的错误。

Phalcon provides a debug component that allows the developer to easily find errors produced in an application created with the framework.

下面的视频中展示了如何工作的:

The following screencast explains how it works:

要打开调试功能只需要如下做:

To enable it, add the following to your bootstrap:

  1. <?php
  2. $debug = new \Phalcon\Debug();
  3. $debug->listen();

注意一定要去掉Try/Catch块才可以, 否则异常信息不会正确的输出(事实上很多时候Phalco显示异常信息是非常耗时的)。

Any Try/Catch blocks must be removed or disabled to make this component work properly.

反射与内省Reflection and Introspection

Phalcon的类的实例通常比一般的类实例更复杂。 这里我们可以使用 `Reflection API`_(反射机制) 或 直接打印其内部状态来观其究竟:

Any instance of a Phalcon class offers exactly the same behavior than a PHP normal one. It’s possible to use the Reflection API or simply print any object to show how is its internal state:

  1. <?php
  2. $router = new Phalcon\Mvc\Router();
  3. print_r($router);

开发者可以非常容易的观察到对象内部的状态。 上面的代码输出如下:

It’s easy to know the internal state of any object. The above example prints the following:

  1. Phalcon\Mvc\Router Object
  2. (
  3. [_dependencyInjector:protected] =>
  4. [_module:protected] =>
  5. [_controller:protected] =>
  6. [_action:protected] =>
  7. [_params:protected] => Array
  8. (
  9. )
  10. [_routes:protected] => Array
  11. (
  12. [0] => Phalcon\Mvc\Router\Route Object
  13. (
  14. [_pattern:protected] => #^/([a-zA-Z0-9\_]+)[/]{0,1}$#
  15. [_compiledPattern:protected] => #^/([a-zA-Z0-9\_]+)[/]{0,1}$#
  16. [_paths:protected] => Array
  17. (
  18. [controller] => 1
  19. )
  20. [_methods:protected] =>
  21. [_id:protected] => 0
  22. [_name:protected] =>
  23. )
  24. [1] => Phalcon\Mvc\Router\Route Object
  25. (
  26. [_pattern:protected] => #^/([a-zA-Z0-9\_]+)/([a-zA-Z0-9\_]+)(/.*)*$#
  27. [_compiledPattern:protected] => #^/([a-zA-Z0-9\_]+)/([a-zA-Z0-9\_]+)(/.*)*$#
  28. [_paths:protected] => Array
  29. (
  30. [controller] => 1
  31. [action] => 2
  32. [params] => 3
  33. )
  34. [_methods:protected] =>
  35. [_id:protected] => 1
  36. [_name:protected] =>
  37. )
  38. )
  39. [_matchedRoute:protected] =>
  40. [_matches:protected] =>
  41. [_wasMatched:protected] =>
  42. [_defaultModule:protected] =>
  43. [_defaultController:protected] =>
  44. [_defaultAction:protected] =>
  45. [_defaultParams:protected] => Array
  46. (
  47. )
  48. )

使用 XDebug Using XDebug

XDebug 是一个非常好(神奇)的调试工具,其和PHP内部调试工具一起为我们提调试工具(可以和PHP内置的调试工具互补)。 XDebug 也是一个PHP扩展, 所以二者可以一起使用,而且不需要额外的配置。

XDebug is an amazing tool that complements the debugging of PHP applications. It is also a C extension for PHP, and you can use it together with Phalcon without additional configuration or side effects.

下面的视频中展示了Phalcon中使用XDebug的情况:

The following screencast shows a Xdebug session with Phalcon:

一旦安装了xdebug, 开发者便可以使用其API来取得更多的异常信息和其它信息:

Once you have xdebug installed, you can use its API to get a more detailed information about exceptions and messages.

我们强烈推荐至少使用XDebug 2.2.3 以提供与Phalcon最佳的兼容性。

We highly recommend use at least XDebug 2.2.3 for a better compatibility with Phalcon

下面的例子中调用了 xdebug_print_function_stack 方法, 并返回了该方法产生的代码跟踪结果.

The following example implements xdebug_print_function_stack to stop the execution and generate a backtrace

  1. <?php
  2. class SignupController extends \Phalcon\Mvc\Controller
  3. {
  4. public function indexAction()
  5. {
  6. }
  7. public function registerAction()
  8. {
  9. // Request variables from html form
  10. $name = $this->request->getPost("name", "string");
  11. $email = $this->request->getPost("email", "email");
  12. // Stop execution and show a backtrace
  13. return xdebug_print_function_stack("stop here!");
  14. $user = new Users();
  15. $user->name = $name;
  16. $user->email = $email;
  17. // Store and check for errors
  18. $user->save();
  19. }
  20. }

这个例子中, XDebug显示出了局部变量和代码的跟踪信息:

In this instance, Xdebug will also show us the variables in the local scope, and a backtrace as well:

  1. Xdebug: stop here! in /Applications/MAMP/htdocs/tutorial/app/controllers/SignupController.php
  2. on line 19
  3. Call Stack:
  4. 0.0383 654600 1. {main}() /Applications/MAMP/htdocs/tutorial/public/index.php:0
  5. 0.0392 663864 2. Phalcon\Mvc\Application->handle()
  6. /Applications/MAMP/htdocs/tutorial/public/index.php:37
  7. 0.0418 738848 3. SignupController->registerAction()
  8. /Applications/MAMP/htdocs/tutorial/public/index.php:0
  9. 0.0419 740144 4. xdebug_print_function_stack()
  10. /Applications/MAMP/htdocs/tutorial/app/controllers/SignupController.php:19

使用xdebug我们可以使用若干种方法来取得关phalcon应用的调试信息。更多信可以参看这里的 XDebug documentation ( XDebug 文档)。

Xdebug provides several ways to get debug and trace information regarding the execution of your application using Phalcon. You can check the XDebug documentation for more information.