<blockquote>最近发现自己写的PHP代码运行结果总跟自己预想的不一样,排查时发现大多是语法错误,在运行之前错误已经种下。可能是自己粗心大意,或者说<code>php -l</code>检测太简单,不过的确是有一些语法错误埋藏得太深(毕竟PHP是动态语言),那么有没有办法,在代码代码正式运行之前,把语法错误全找出来呢?</blockquote> <p>这里介绍一款PHP代码静态分析工具:<a href="https://github.com/phpstan/phpstan" rel="nofollow noreferrer">PHPStan</a>,不需要运行代码,也可以对代码进行严格的语法检测,尽量将代码运行错误率降到最低。</p> <h2>PHPStan</h2> <h3>安装</h3> <p>目前,PHPStan<code>V0.10.2</code>要求系统环境的PHP版本不低于7.1。用Composer全局安装:</p> \`\`\`$ composer global require phpstan/phpstan \`\`\`
<h3>使用</h3> <p>PHPStan静态分析的使用方法十分简单:</p> \`\`\`$ phpstan analyse \[-c|--configuration CONFIGURATION\] \[-l|--level LEVEL\] \[--no-progress\] \[--debug\] \[-a|--autoload-file AUTOLOAD-FILE\] \[--errorFormat ERRORFORMAT\] \[--memory-limit MEMORY-LIMIT\] \[--\] \[<paths>\]... \`\`\`
<ul> <li>configuration:运行配置文件的路径;</li> <li>level:严格级别,0-7,越大越严格;</li> <li>no-progress:不显示进度;</li> <li>debug:debug模式;</li> <li>autoload-file:自动加载文件的路径;</li> <li>errorFormat:错误格式;</li> <li>memory-limit:内存限制;</li> <li>paths:待分析的文件路径。</li> </ul> <p>比如,分析一个PHP文件:</p> \`\`\`$ phpstan analyse --level=7 --autoload-file=/PATH/TO/vendor/autoload.php /PATH/TO/someone.php \`\`\`
<h2>PHPStan in VSCode</h2> <p>当然,语法分析应该是编辑器做的事,写完代码还要切换到命令终端执行<code>phpstan</code>,未免过于繁琐。所以这里推荐一款VSCode扩展:<a href="https://marketplace.visualstudio.com/items?itemName=breezelin.phpstan" rel="nofollow noreferrer">PHP Static Analysis</a>。</p>

<p>首先,用Composer全局安装PHPStan;然后,在VSCode的扩展管理中搜索<code>PHP Static Analysis</code>,安装第一个匹配的扩展;重载VSCode重载窗口后,扩展会自动分析VSCode下打开的PHP文件。</p> <p>运行效果:<br></p>

<p>比如,声明了一个变量未调用,调用了一个未声明的变量和调用了一个未定义的方法等等这样错误都会被检测出了。</p> <p>不过,宽松一点地来说,其实<code>$this->array()</code>方法是存在的,只是通过魔术方法<code>\_\_call()</code>实现的。</p> <h2>PHPStan with Laravel</h2> <p>高严格级别的PHPStan检测到调用未声明的类方法时,会报告类中方法不存在的错误,即使这个类定义了<code>\_\_call()</code>或<code>\_\_callStatic()</code>。</p> <p>很多应用框架为了优雅,大量使用了魔术方法,比如<a href="https://laravel.com/" rel="nofollow noreferrer">Laravel</a>。<br>用PHPStan检测Laravel项目,自然会报告很多调用未声明类方法的错误,对于这个问题,可以借助<a href="https://github.com/barryvdh/laravel-ide-helper" rel="nofollow noreferrer">laravel-ide-helper</a>来降低误报。</p> <h3>安装laravel-ide-helper</h3> \`\`\`$ cd /PATH/TO/LARAVEL\_PROJECT $ composer require barryvdh/laravel-ide-helper \`\`\`
<h3>注入LaravelIdeHelper</h3> <p>编辑<code>app/Providers/AppServiceProvider.php</code>里的注册方法:</p>
1<?php
2 ...
3 public function register()
4 {
5 if ($this->app->environment() !== 'production') {
6 $this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
7 }
8 // ...
9 }
<h3>生成\_ide\_helper.php</h3> \`\`\`$ cd /PATH/TO/LARAVEL\_PROJECT $ php artisan ide-helper:generate \`\`\`
<p>这时,Laravel框架中的Facade类,原本通过<code>\_\_callStatic()</code>获取的静态方法,全部在\_ide\_helper.php声明了,在PHPStan检测Laravel项目代码时引入<code>\_ide\_helper.php</code>文件,就可以减少误报。</p> <h3>PHPStan配置</h3> <p>在Laravel项目的根目录下,新建<code>phpstan.neon</code>文件:</p> \`\`\` parameters: autoload\_files: - %currentWorkingDirectory%/\_ide\_helper.php \`\`\`
<p>在Laravel项目的根目录下,执行<code>phpstan</code>命令时,会自动使用<code>phpstan.neon</code>这个配置。</p> <h2>最后</h2> <p>代码的语法错误,应该在编写的时候及时发现,尽量减少正式运行时错误。</p>
原文地址:https://segmentfault.com/a/1190000015956085