在我们开发项目的过程中,不可避免的会使用一些开软程序,因为使用开源程序可以缩短我们的开发周期,降低研发成本。
但是在使用过程中,难免会碰到各种坑,这个时候,就要求程序员拥有分析开源项目的能力,因为并非是所有开源项目都会拥有一个稳定的维护团队和健全的文档(毕竟开源项目很少有盈利的)。
在进行 PHP 研发过程中,我们可以使用以下5中方式来进行代码分析:
- 看文档
- Xdebug做调试
- 自带函数(debug_backtrace, debug_print_backtrace, var_export, var_dump, get_inclued_files)
- SocketLog(不能var_dump的地方ajax、api,var_dump了也看不见的地方,cron 脚本,队列)
- 思维整理 (UML、思维导图)
为什么要把看文档排在第一位?
当我们第一次拿到开源程序的代码时,很多人会第一反应去看它的源代码,但是如果说我们要了解它的编程思想,就看编程思想而言是看文档,还是看代码要容易呢?
如果在不了解开源代码的功能就去了解代码的话,其实很难能够弄懂他的编程思想。
有时候开源程序没有提供文档,我们可以使用 PHPDocumentor 将注释提取成文档。
PHPDocumentor: http://www.phpdoc.org/
使用 Xdebug 调试代码
我们可以使用 Xdebug 联合 IDE 通过断点调试放慢代码执行流程,当程序执行到用户指定的断点后,可以到该位置停顿,然后输出在该变量中的值,可以一步一步的分析代码,如果碰到难懂的代码就可以通过这种形式来进行调试代码。
Xdebug: https://xdebug.org
PHP自带函数
打出调用栈:
debug_backtrace();
debug_print_backtrace();
如果我们自己去看执行流程,就要跟着函数一步一步的走,可是如果使用调用栈,就可以清晰明了的看清。
我们可以通过这两个函数查看 ThinkPHP 是如何调用控制器的,在这里,我使用的 ThinkPHP5.0,在这里我们需要从下往上看。
array(7) {
[0] => array(5) {
["function"] => string(5) "index"
["class"] => string(26) "app\index\controller\Index"
["object"] => object(app\index\controller\Index)#3 (0) {
}
["type"] => string(2) "->"
["args"] => array(0) {
}
}
[1] => array(7) {
["file"] => string(70) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/App.php"
["line"] => int(343)
["function"] => string(10) "invokeArgs"
["class"] => string(16) "ReflectionMethod"
["object"] => object(ReflectionMethod)#4 (2) {
["name"] => string(5) "index"
["class"] => string(26) "app\index\controller\Index"
}
["type"] => string(2) "->"
["args"] => array(2) {
[0] => object(app\index\controller\Index)#3 (0) {
}
[1] => array(0) {
}
}
}
//.....省略
}
我们可以来分析一下 ThinkPHP5.0的调用步骤:ß
- 在入口文件的第17行调用加载了 start.php
- 在 start.php 的第19行执行了 thinkApp::start()方法
- 然后在 APP.php 中执行了 exec()方法.....
debug_backtrace 显示的是详细信息,如果想要简单的查看调用,可以使用debug_print_backtrace
函数直接打印输出堆栈的调用信息。
这样我们就可以分析出,ThinkPHP 的执行流程,也就四五分钟的时间。
当我们需要输出变量的时候,我们应该使用 var_dump(),因为var_dump 可以直观的看出数组的结构。
当我们在在向日志文件输出数组的时候,我们可以使用 var_export()
进行输出。
1,
1 => 2,
2 =>
array (
0 => 'a',
1 => 'b',
2 => 'c',
),
)
*/
另外我们可以通过 get_included_files来获取当前脚本文件都加载了哪些文件。
array(23) {
[0] => string(56) "/Users/maksim/Downloads/thinkphp_5.0.20/public/index.php"
[1] => string(58) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/start.php"
[2] => string(57) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/base.php"
[3] => string(73) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Loader.php"
[4] => string(75) "/Users/maksim/Downloads/thinkphp_5.0.20/vendor/composer/autoload_static.php"
[5] => string(72) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Error.php"
[6] => string(73) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Config.php"
[7] => string(63) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/convention.php"
[8] => string(70) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/App.php"
[9] => string(74) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Request.php"
[10] => string(62) "/Users/maksim/Downloads/thinkphp_5.0.20/application/config.php"
[11] => string(64) "/Users/maksim/Downloads/thinkphp_5.0.20/application/database.php"
[12] => string(67) "/Users/maksim/Downloads/thinkphp_5.0.20/application/extra/queue.php"
[13] => string(71) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Hook.php"
[14] => string(60) "/Users/maksim/Downloads/thinkphp_5.0.20/application/tags.php"
[15] => string(62) "/Users/maksim/Downloads/thinkphp_5.0.20/application/common.php"
[16] => string(70) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Env.php"
[17] => string(59) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/helper.php"
[18] => string(71) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Lang.php"
[19] => string(63) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/lang/zh-cn.php"
[20] => string(61) "/Users/maksim/Downloads/thinkphp_5.0.20/application/route.php"
[21] => string(72) "/Users/maksim/Downloads/thinkphp_5.0.20/thinkphp/library/think/Route.php"
[22] => string(78) "/Users/maksim/Downloads/thinkphp_5.0.20/application/index/controller/Index.php"
}
上面都是用PHP 自带的函数来做代码分析,下面来讲解一下利用 SocketLog 来分析源代码。
SocketLog 可以把我们的一些日志打到浏览器的调试工具上面。
比如说 SQL 语句,点开后可以查看调用栈,通过这些信息,我们就可以快速定位我们想要修改的代码。其实 SocketLog 还可以做微信调试。
详细的使用方法可以通过 github 进行查看:
https://github.com/luofei614/...
我们可以通过一些思维导图的工具来帮助我们分析业务逻辑。
我们还可以通过 UML 图形来整理类之间的关系,我们可以看 《大象UML 》来了解 UML 建模。