{"id":6346,"date":"2019-08-29T19:59:19","date_gmt":"2019-08-29T14:29:19","guid":{"rendered":"http:\/\/kalilinuxtutorials.com\/?p=6346"},"modified":"2019-08-29T19:59:19","modified_gmt":"2019-08-29T14:29:19","slug":"phpstan-php-static-analysis-tool","status":"publish","type":"post","link":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/","title":{"rendered":"PHPStan &#8211; PHP Static Analysis Tool &#8211; Discover Bugs In Your Code Without Running It"},"content":{"rendered":"\n<p><strong>PHPStan<\/strong> focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line. <\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><strong>Prerequisites<\/strong><\/p>\n\n\n\n<p>PHPStan requires PHP &gt;= 7.1. You have to run it in environment with PHP 7.x but the actual code does not have to use PHP 7.x features. (Code written for PHP 5.6 and earlier can run on 7.x mostly unmodified.)<\/p>\n\n\n\n<p>PHPStan works best with modern object-oriented code. The more strongly-typed your code is, the more information you give PHPStan to work with.<\/p>\n\n\n\n<p>Properly annotated and typehinted code (class properties, function and method arguments, return types) helps not only static analysis tools but also other people that work with the code to understand it.<\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#installation\"><\/a><strong>Installation<\/strong><\/p>\n\n\n\n<p>To start performing analysis on your code, require PHPStan in&nbsp;<a href=\"https:\/\/getcomposer.org\/\">Composer<\/a>:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">composer require &#8211;dev phpstan\/phpstan\n<\/p>\n\n\n\n<p>Composer will install PHPStan&#8217;s executable in its&nbsp;<code><strong>bin-dir<\/strong><\/code>&nbsp;which defaults to&nbsp;<code><strong>vendor\/bin<\/strong><\/code>.<\/p>\n\n\n\n<p>If you have conflicting dependencies or you want to install PHPStan globally, the best way is via a PHAR archive. You will always find the latest stable PHAR archive below the&nbsp;<a href=\"https:\/\/github.com\/phpstan\/phpstan\/releases\">release notes<\/a>. You can also use the&nbsp;<a href=\"https:\/\/packagist.org\/packages\/phpstan\/phpstan-shim\">phpstan\/phpstan-shim<\/a>&nbsp;package to install PHPStan via Composer without the risk of conflicting dependencies.<\/p>\n\n\n\n<p>You can also use&nbsp;<a href=\"https:\/\/github.com\/phpstan\/docker-image\">PHPStan via Docker<\/a>.<\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#first-run\"><\/a><strong>First Run<\/strong><\/p>\n\n\n\n<p>To let PHPStan analyse your codebase, you have to use the&nbsp;<code>analyse<\/code>&nbsp;command and point it to the right directories.<\/p>\n\n\n\n<p>So, for example if you have your classes in directories&nbsp;<code>src<\/code>&nbsp;and&nbsp;<code>tests<\/code>, you can run PHPStan like this:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\"><strong>vendor\/bin\/phpstan analyse src tests<\/strong><\/p>\n\n\n\n<p>PHPStan will probably find some errors, but don&#8217;t worry, your code might be just fine. Errors found on the first run tend to be:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Extra arguments passed to functions (e. g. function requires two arguments, the code passes three)<\/li><li>Extra arguments passed to print\/sprintf functions (e. g. format string contains one placeholder, the code passes two values to replace)<\/li><li>Obvious errors in dead code<\/li><li>Magic behaviour that needs to be defined. See&nbsp;<a href=\"https:\/\/github.com\/phpstan\/phpstan#extensibility\">Extensibility<\/a>.<\/li><\/ul>\n\n\n\n<p>After fixing the obvious mistakes in the code, look to the following section for all the configuration options that will bring the number of reported errors to zero making PHPStan suitable to run as part of your continuous integration script.<\/p>\n\n\n\n<p style=\"text-align:center\"><strong>Also Read &#8211; <a href=\"https:\/\/kalilinuxtutorials.com\/sublert-security-certificate-transparency\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Sublert : Security &amp; Reconnaissance Tool Which Leverages Certificate Transparency (opens in a new tab)\">Sublert : Security &amp; Reconnaissance Tool Which Leverages Certificate Transparency<\/a><\/strong><\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#rule-levels\"><\/a><strong>Rule levels<\/strong><\/p>\n\n\n\n<p>If you want to use PHPStan but your codebase isn&#8217;t up to speed with strong typing and PHPStan&#8217;s strict checks, you can choose from currently 8 levels (0 is the loosest and 7 is the strictest) by passing&nbsp;<code><strong>--level<\/strong><\/code>&nbsp;to&nbsp;<code><strong>analyse<\/strong><\/code>&nbsp;command. Default level is&nbsp;<code><strong>0<\/strong><\/code>.<\/p>\n\n\n\n<p>This feature enables incremental adoption of PHPStan checks. You can start using PHPStan with a lower rule level and increase it when you feel like it.<\/p>\n\n\n\n<p>You can also use&nbsp;<code><strong>--level max<\/strong><\/code>&nbsp;as an alias for the highest level. This will ensure that you will always use the highest level when upgrading to new versions of PHPStan. Please note that this can create a significant obstacle when upgrading to a newer version because you might have to fix a lot of code to bring the number of errors down to zero.<\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><strong>Configuration<\/strong><\/p>\n\n\n\n<p>Config file is passed to the&nbsp;<code>phpstan<\/code>&nbsp;executable with&nbsp;<code>-c<\/code>&nbsp;option:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">vendor\/bin\/phpstan analyse -l 4 -c phpstan.neon src tests<\/p>\n\n\n\n<p>When using a custom project config file, you have to pass the&nbsp;<code><strong>--level<\/strong><\/code><strong>&nbsp;(<\/strong><code><strong>-l<\/strong><\/code><strong>)<\/strong> option to&nbsp;<code><strong>analyse<\/strong><\/code><strong>&nbsp;<\/strong>command (default value does not apply here).<\/p>\n\n\n\n<p>If you do not provide config file explicitly, PHPStan will look for files named&nbsp;<code>phpstan.neon<\/code>&nbsp;or&nbsp;<code>phpstan.neon.dist<\/code>&nbsp;in current directory.<\/p>\n\n\n\n<p>The resolution priority is as such:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>If config file is provided on command line, it is used.<\/li><li>If config file&nbsp;<code>phpstan.neon<\/code>&nbsp;exists in current directory, it will be used.<\/li><li>If config file&nbsp;<code>phpstan.neon.dist<\/code>&nbsp;exists in current directory, it will be used.<\/li><li>If none of the above is true, no config will be used.<\/li><\/ol>\n\n\n\n<p><a href=\"https:\/\/ne-on.org\/\">NEON file format<\/a>&nbsp;is very similar to YAML. All the following options are part of the&nbsp;<code>parameters<\/code>&nbsp;section.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#configuration-variables\"><\/a><strong>Configuration variables<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code><strong>%rootDir%<\/strong><\/code>&nbsp;&#8211; root directory where PHPStan resides (i.e.&nbsp;<code><strong>vendor\/phpstan\/phpstan<\/strong><\/code>&nbsp;in Composer installation)<\/li><li><code><strong>%currentWorkingDirectory%<\/strong><\/code>&nbsp;&#8211; current working directory where PHPStan was executed<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#configuration-options\"><\/a>Configuration options<\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li><code><strong>tmpDir<\/strong><\/code><strong>&nbsp;<\/strong>&#8211; specifies the temporary directory used by PHPStan cache (defaults to&nbsp;<code><strong>sys_get_temp_dir() . '\/phpstan'<\/strong><\/code>)<\/li><li><code><strong>level<\/strong><\/code>&nbsp;&#8211; specifies analysis level &#8211; if specified,&nbsp;<code><strong>-l<\/strong><\/code>&nbsp;option is not required<\/li><li><code><strong>paths<\/strong><\/code><strong>&nbsp;<\/strong>&#8211; specifies analysed paths &#8211; if specified, paths are not required to be passed as arguments<\/li><\/ul>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#autoloading\"><\/a><strong>Autoloading<\/strong><\/p>\n\n\n\n<p>PHPStan uses Composer autoloader so the easiest way how to autoload classes is through the&nbsp;<code><strong>autoload<\/strong><\/code><strong>\/<\/strong><code><strong>autoload-dev<\/strong><\/code>sections in composer.json.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#specify-paths-to-scan\"><\/a><strong>Specify paths to scan<\/strong><\/p>\n\n\n\n<p>If PHPStan complains about some non-existent classes and you&#8217;re sure the classes exist in the codebase AND you don&#8217;t want to use Composer autoloader for some reason, you can specify directories to scan and concrete files to include using<code><strong>autoload_directories<\/strong><\/code>&nbsp;and&nbsp;<code><strong>autoload_files<\/strong><\/code><strong>&nbsp;<\/strong>array parameters:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\"><strong>parameters:<br>     autoload_directories:<br>         &#8211; %rootDir%\/..\/..\/..\/build<br>     autoload_files:<br>         &#8211; %rootDir%\/..\/..\/..\/generated\/routes\/GeneratedRouteList.php<\/strong><\/p>\n\n\n\n<p><code><strong>%rootDir%<\/strong><\/code>&nbsp;is expanded to the root directory where PHPStan resides.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#autoloading-for-global-installation\"><\/a><strong>Autoloading for global installation<\/strong><\/p>\n\n\n\n<p>PHPStan supports global installation using&nbsp;<a href=\"https:\/\/getcomposer.org\/doc\/03-cli.md#global\"><code><strong>composer global<\/strong><\/code><\/a>&nbsp;or via a&nbsp;<a href=\"https:\/\/github.com\/phpstan\/phpstan#installation\">PHAR archive<\/a>. In this case, it&#8217;s not part of the project autoloader, but it supports autodiscovery of the Composer autoloader from current working directory residing in&nbsp;<code>vendor\/<\/code>:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">cd \/path\/to\/project <br>phpstan analyse src tests # looks for autoloader at \/path\/to\/project\/vendor\/autoload.php<\/p>\n\n\n\n<p>If you have your dependencies installed at a different path or you&#8217;re running PHPStan from a different directory, you can specify the path to the autoloader with the&nbsp;<code><strong>--autoload-file|-a<\/strong><\/code>&nbsp;option:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\"><strong>phpstan analyse &#8211;autoload-file=\/path\/to\/autoload.php src tests<\/strong><\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#exclude-files-from-analysis\"><\/a><strong>Exclude files from analysis<\/strong><\/p>\n\n\n\n<p>If your codebase contains some files that are broken on purpose (e. g. to test behaviour of your application on files with invalid PHP code), you can exclude them using the&nbsp;<code><strong>excludes_analyse<\/strong><\/code>&nbsp;array parameter. String at each line is used as a pattern for the&nbsp;<a href=\"https:\/\/secure.php.net\/manual\/en\/function.fnmatch.php\"><code><strong>fnmatch<\/strong><\/code><\/a><strong>&nbsp;<\/strong>function.<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    excludes_analyse:<br>\n        &#8211; %rootDir%\/..\/..\/..\/tests\/<em>\/data\/<\/em><\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#include-custom-extensions\"><\/a><strong>Include custom extensions<\/strong><\/p>\n\n\n\n<p>If your codebase contains php files with extensions other than the standard .php extension then you can add them to the&nbsp;<code><strong>fileExtensions<\/strong><\/code>&nbsp;array parameter:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    fileExtensions:<br>\n        &#8211; php<br>\n        &#8211; module<br>\n        &#8211; inc<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#universal-object-crates\"><\/a><strong>Universal object crates<\/strong><\/p>\n\n\n\n<p>Classes without predefined structure are common in PHP applications. They are used as universal holders of data &#8211; any property can be set and read on them. Notable examples include&nbsp;<code><strong>stdClass<\/strong><\/code><strong>,&nbsp;<\/strong><code><strong>SimpleXMLElement<\/strong><\/code>&nbsp;(these are enabled by default), objects with results of database queries etc. Use&nbsp;<code><strong>universalObjectCratesClasses<\/strong><\/code>&nbsp;array parameter to let PHPStan know which classes with these characteristics are used in your codebase:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    universalObjectCratesClasses:<br>\n        &#8211; Dibi\\Row<br>\n        &#8211; Ratchet\\ConnectionInterface<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#add-non-obviously-assigned-variables-to-scope\"><\/a><strong>Add non-obviously assigned variables to scope<\/strong><\/p>\n\n\n\n<p>If you use some variables from a try block in your catch blocks, set&nbsp;<code><strong>polluteCatchScopeWithTryAssignments<\/strong><\/code>&nbsp;boolean parameter to&nbsp;<code><strong>true<\/strong><\/code>.<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">try {<br>\n    $author = $this-&gt;getLoggedInUser();<br>\n    $post = $this-&gt;postRepository-&gt;getById($id);<br>\n} catch (PostNotFoundException $e) {<br>\n    \/\/ $author is probably defined here<br>\n    throw new ArticleByAuthorCannotBePublished($author);<br>\n}<\/p>\n\n\n\n<p>If you are enumerating over all possible situations in if-elseif branches and PHPStan complains about undefined variables after the conditions, you can write an else branch with throwing an exception:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">if (somethingIsTrue()) {<br>     $foo = true;<br> } elseif (orSomethingElseIsTrue()) {<br>     $foo = false;<br> } else {<br>     throw new ShouldNotHappenException();<br> }<br>doFoo($foo);<\/p>\n\n\n\n<p>I recommend leaving&nbsp;<code><strong>polluteCatchScopeWithTryAssignments<\/strong><\/code>&nbsp;set to&nbsp;<code><strong>false<\/strong><\/code>&nbsp;because it leads to a clearer and more maintainable code.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#custom-early-terminating-method-calls\"><\/a><strong>Custom early terminating method calls<\/strong><\/p>\n\n\n\n<p>Previous example showed that if a condition branches end with throwing an exception, that branch does not have to define a variable used after the condition branches end.<\/p>\n\n\n\n<p>But exceptions are not the only way how to terminate execution of a method early. Some specific method calls can be perceived by project developers also as early terminating &#8211; like a&nbsp;<code><strong>redirect()<\/strong><\/code>&nbsp;that stops execution by throwing an internal exception.<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">if (somethingIsTrue()) {<br>     $foo = true;<br> } elseif (orSomethingElseIsTrue()) {<br>     $foo = false;<br> } else {<br>     $this-&gt;redirect(&#8216;homepage&#8217;);<br> }<br>doFoo($foo);<\/p>\n\n\n\n<p>These methods can be configured by specifying a class on whose instance they are called like this:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    earlyTerminatingMethodCalls:<br>\n        Nette\\Application\\UI\\Presenter:<br>\n            &#8211; redirect<br>\n            &#8211; redirectUrl<br>\n            &#8211; sendJson<br>\n            &#8211; sendResponse<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#ignore-error-messages-with-regular-expressions\"><\/a><strong>Ignore error messages with regular expressions<\/strong><\/p>\n\n\n\n<p>If some issue in your code base is not easy to fix or just simply want to deal with it later, you can exclude error messages from the analysis result with regular expressions:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    ignoreErrors:<br>\n        &#8211; &#8216;#Call to an undefined method [a-zA-Z0-9\\_]+::method()#&#8217;<br>\n        &#8211; &#8216;#Call to an undefined method [a-zA-Z0-9\\_]+::expects()#&#8217;<br>\n        &#8211; &#8216;#Access to an undefined property PHPUnit_Framework_MockObject_MockObject::\\$[a-zA-Z0-9_]+#&#8217;<br>\n        &#8211; &#8216;#Call to an undefined method PHPUnit_Framework_MockObject_MockObject::[a-zA-Z0-9_]+()#&#8217;<\/p>\n\n\n\n<p>To exclude an error in a specific directory or file, specify a&nbsp;<code>path<\/code>&nbsp;or&nbsp;<code>paths<\/code>&nbsp;along with the&nbsp;<code><strong>message<\/strong><\/code>:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    ignoreErrors:<br>\n        &#8211;<br>\n            message: &#8216;#Call to an undefined method [a-zA-Z0-9\\_]+::method()#&#8217;<br>\n            path: %currentWorkingDirectory%\/some\/dir\/SomeFile.php<br>\n        &#8211;<br>\n            message: &#8216;#Call to an undefined method [a-zA-Z0-9\\_]+::method()#&#8217;<br>\n            paths:<br>\n                &#8211; %currentWorkingDirectory%\/some\/dir\/*<br>\n                &#8211; %currentWorkingDirectory%\/other\/dir\/*<br>\n        &#8211; &#8216;#Other error to catch anywhere#&#8217;<\/p>\n\n\n\n<p>If some of the patterns do not occur in the result anymore, PHPStan will let you know and you will have to remove the pattern from the configuration. You can turn off this behavior by setting&nbsp;<code><strong>reportUnmatchedIgnoredErrors<\/strong><\/code>&nbsp;to&nbsp;<code><strong>false<\/strong><\/code><strong>&nbsp;<\/strong>in PHPStan configuration.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#bootstrap-file\"><\/a><strong>Bootstrap file<\/strong><\/p>\n\n\n\n<p>If you need to initialize something in PHP runtime before PHPStan runs (like your own autoloader), you can provide your own bootstrap file:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">parameters:<br>\n    bootstrap: %rootDir%\/..\/..\/..\/phpstan-bootstrap.php<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#custom-rules\"><\/a><strong>Custom rules<\/strong><\/p>\n\n\n\n<p>PHPStan allows writing custom rules to check for specific situations in your own codebase. Your rule class needs to implement the&nbsp;<code><strong>PHPStan\\Rules\\Rule<\/strong><\/code>&nbsp;interface and registered as a service in the configuration file:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">services:<br>\n    &#8211;<br>\n        class: MyApp\\PHPStan\\Rules\\DefaultValueTypesAssignedToPropertiesRule<br>\n        tags:<br>\n            &#8211; phpstan.rules.rule<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>For inspiration on how to implement a rule turn to&nbsp;<a href=\"https:\/\/github.com\/phpstan\/phpstan\/tree\/master\/src\/Rules\">src\/Rules<\/a>&nbsp;to see a lot of built-in rules.<\/li><li>Check out also&nbsp;<a href=\"https:\/\/github.com\/phpstan\/phpstan-strict-rules\">phpstan-strict-rules<\/a>&nbsp;repository for extra strict and opinionated rules for PHPStan!<\/li><li>Check as well&nbsp;<a href=\"https:\/\/github.com\/phpstan\/phpstan-deprecation-rules\">phpstan-deprecation-rules<\/a>&nbsp;for rules that detect usage of deprecated classes, methods, properties, constants and traits!<\/li><\/ul>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#custom-error-formatters\"><\/a><strong>Custom error formatters<\/strong><\/p>\n\n\n\n<p>PHPStan outputs errors via formatters. You can customize the output by implementing the&nbsp;<code><strong>ErrorFormatter<\/strong><\/code>&nbsp;interface in a new class and add it to the configuration. For existing formatters, see next chapter.<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">interface ErrorFormatter<br>\n{<br>\n    \/**<br>\n     * Formats the errors and outputs them to the console.<br>\n     *<br>\n     * @param \\PHPStan\\Command\\AnalysisResult $analysisResult<br>\n     * @param \\Symfony\\Component\\Console\\Style\\OutputStyle $style<br>\n     * @return int Error code.<br>\n     *\/<br>\n    public function formatErrors(<br>\n        AnalysisResult $analysisResult,<br>\n        \\Symfony\\Component\\Console\\Style\\OutputStyle $style<br>\n    ): int;<br>\n}<\/p>\n\n\n\n<p>Register the formatter in your&nbsp;<code><strong>phpstan.neon<\/strong><\/code>:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">services:<br>\n    errorFormatter.awesome:<br>\n        class: App\\PHPStan\\AwesomeErrorFormatter<\/p>\n\n\n\n<p>Use the name part after&nbsp;<code><strong>errorFormatter.<\/strong><\/code>&nbsp;as the CLI option value:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">vendor\/bin\/phpstan analyse -c phpstan.neon -l 4 &#8211;error-format awesome src tests<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#existing-error-formatters-to-be-used\"><\/a><strong>Existing error formatters to be used<\/strong><\/p>\n\n\n\n<p>You can pass the following keywords to the&nbsp;<code><strong>--error-format=X<\/strong><\/code>&nbsp;parameter in order to affect the output:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code><strong>table<\/strong><\/code>: Default. Grouped errors by file, colorized. For human consumption.<\/li><li><code><strong>raw<\/strong><\/code>: Contains one error per line, with path to file, line number, and error description<\/li><li><code><strong>checkstyle<\/strong><\/code>: Creates a checkstyle.xml compatible output. Note that you&#8217;d have to redirect output into a file in order to capture the results for later processing.<\/li><li><code><strong>json<\/strong><\/code>: Creates minified .json output without whitespaces. Note that you&#8217;d have to redirect output into a file in order to capture the results for later processing.<\/li><li><code><strong>prettyJson<\/strong><\/code>: Creates human readable .json output with whitespaces and indentations. Note that you&#8217;d have to redirect output into a file in order to capture the results for later processing.<\/li><\/ul>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#class-reflection-extensions\"><\/a><strong>Class Reflection Extensions<\/strong><\/p>\n\n\n\n<p>Classes in PHP can expose &#8220;magical&#8221; properties and methods decided in run-time using class methods like&nbsp;<code><strong>__get<\/strong><\/code><strong>,&nbsp;<\/strong><code><strong>__set<\/strong><\/code>and&nbsp;<code><strong>__call<\/strong><\/code>. Because PHPStan is all about static analysis (testing code for errors without running it), it has to know about those properties and methods beforehand.<\/p>\n\n\n\n<p>When PHPStan stumbles upon a property or a method that is unknown to built-in class reflection, it iterates over all registered class reflection extensions until it finds one that defines the property or method.<\/p>\n\n\n\n<p>Class reflection extension cannot have&nbsp;<code><strong>PHPStan\\Broker\\Broker<\/strong><\/code>&nbsp;(service for obtaining class reflections) injected in the constructor due to circular reference issue, but the extensions can implement&nbsp;<code><strong>PHPStan\\Reflection\\BrokerAwareExtension<\/strong><\/code>interface to obtain Broker via a setter.<\/p>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#properties-class-reflection-extensions\"><\/a><strong>Properties class reflection extensions<\/strong><\/p>\n\n\n\n<p>This extension type must implement the following interface:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">namespace PHPStan\\Reflection;<br>interface PropertiesClassReflectionExtension<br> {<br>public function hasProperty(ClassReflection $classReflection, string $propertyName): bool;<br>public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection;<br>}<\/p>\n\n\n\n<p>Most likely you will also have to implement a new&nbsp;<code><strong>PropertyReflection<\/strong><\/code>&nbsp;class:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">namespace PHPStan\\Reflection;<br>\ninterface PropertyReflection<br>\n{<br>\npublic function getType(): Type;<br>\npublic function getDeclaringClass(): ClassReflection;<br>\npublic function isStatic(): bool;<br>\npublic function isPrivate(): bool;<br>\npublic function isPublic(): bool;<br>\n}<\/p>\n\n\n\n<p>This is how you register the extension in project&#8217;s PHPStan config file:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">services:<br>class: App\\PHPStan\\PropertiesFromAnnotationsClassReflectionExtension tags:<br>phpstan.broker.propertiesClassReflectionExtension<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#methods-class-reflection-extensions\"><\/a><strong>Methods class reflection extensions<\/strong><\/p>\n\n\n\n<p>This extension type must implement the following interface:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">namespace PHPStan\\Reflection;<br>\ninterface MethodsClassReflectionExtension<br>\n{<br>\n    public function hasMethod(ClassReflection $classReflection, string $methodName): bool;<br>\n    public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection;<br>\n}<\/p>\n\n\n\n<p>Most likely you will also have to implement a new&nbsp;<code><strong>MethodReflection<\/strong><\/code>&nbsp;class:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">namespace PHPStan\\Reflection;<br>\ninterface MethodReflection<br>\n{<br>\n    public function getDeclaringClass(): ClassReflection;<br>\n    public function getPrototype(): self;<br>\n    public function isStatic(): bool;<br>\n    public function isPrivate(): bool;<br>\n    public function isPublic(): bool;<br>\n    public function getName(): string;<br>\n    \/**<br>\n     * @return \\PHPStan\\Reflection\\ParameterReflection[]<br>\n     *\/<br>\n    public function getParameters(): array;<br>\n    public function isVariadic(): bool;<br>\n    public function getReturnType(): Type;<br>\n}<\/p>\n\n\n\n<p>This is how you register the extension in project&#8217;s PHPStan config file:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">services:<br>\n    &#8211;<br>\n    class: App\\PHPStan\\EnumMethodsClassReflectionExtension<br>\n    tags:<br>\n        &#8211; phpstan.broker.methodsClassReflectionExtension<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/phpstan\/phpstan#dynamic-return-type-extensions\"><\/a><strong>Dynamic return type extensions<\/strong><\/p>\n\n\n\n<p>If the return type of a method is not always the same, but depends on an argument passed to the method, you can specify the return type by writing and registering an extension.<\/p>\n\n\n\n<p>Because you have to write the code with the type-resolving logic, it can be as complex as you want.<\/p>\n\n\n\n<p>After writing the sample extension, the variable&nbsp;<code><strong>$mergedArticle<\/strong><\/code>&nbsp;will have the correct type:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">$mergedArticle = $this-&gt;entityManager-&gt;merge($article);<br>\n\/\/ $mergedArticle will have the same type as $article<\/p>\n\n\n\n<p>This is the interface for dynamic return type extension:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">namespace PHPStan\\Type;<br>\nuse PhpParser\\Node\\Expr\\MethodCall;<br>\nuse PHPStan\\Analyser\\Scope;<br>\nuse PHPStan\\Reflection\\MethodReflection;<br>\ninterface DynamicMethodReturnTypeExtension<br>\n{<br>\n    public function getClass(): string;<br>\n    public function isMethodSupported(MethodReflection $methodReflection): bool;<br>\n    public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type;<br>\n}<\/p>\n\n\n\n<p>And this is how you&#8217;d write the extension that correctly resolves the EntityManager::merge() return type:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">public function getClass(): string<br>\n{<br>\n    return \\Doctrine\\ORM\\EntityManager::class;<br>\n}<br>\npublic function isMethodSupported(MethodReflection $methodReflection): bool<br>\n{<br>\n    return $methodReflection-&gt;getName() === &#8216;merge&#8217;;<br>\n}<br>\npublic function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type<br>\n{<br>\n    if (count($methodCall-&gt;args) === 0) {<br>\n        return \\PHPStan\\Reflection\\ParametersAcceptorSelector::selectFromArgs(<br>\n            $scope,<br>\n            $methodCall-&gt;args,<br>\n            $methodReflection-&gt;getVariants()<br>\n        )-&gt;getReturnType();<br>\n    }<br>\n    $arg = $methodCall-&gt;args[0]-&gt;value;<br>\n    return $scope-&gt;getType($arg);<br>\n}<\/p>\n\n\n\n<p>And finally, register the extension to PHPStan in the project&#8217;s config file:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">services:<br>\n    &#8211;<br>\n    class: App\\PHPStan\\EntityManagerDynamicReturnTypeExtension<br>\n    tags:<br>\n    &#8211; phpstan.broker.dynamicMethodReturnTypeExtension<\/p>\n\n\n\n<p>There&#8217;s also an analogous functionality for:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>static methods<\/strong>&nbsp;using&nbsp;<code><strong>DynamicStaticMethodReturnTypeExtension<\/strong><\/code>&nbsp;interface and&nbsp;<code><strong>phpstan.broker.dynamicStaticMethodReturnTypeExtension<\/strong><\/code>&nbsp;service tag.<\/li><li><strong>functions<\/strong>&nbsp;using&nbsp;<code><strong>DynamicFunctionReturnTypeExtension<\/strong><\/code>&nbsp;interface and&nbsp;<code><strong>phpstan.broker.dynamicFunctionReturnTypeExtension<\/strong><\/code>&nbsp;service tag.<\/li><\/ul>\n\n\n\n<p style=\"text-align:center\" class=\"has-background has-light-green-cyan-background-color\"><a href=\"https:\/\/github.com\/phpstan\/phpstan#type-specifying-extensions\"><\/a><strong>Type-specifying extensions<\/strong><\/p>\n\n\n\n<p>These extensions allow you to specify types of expressions based on certain pre-existing conditions. This is best illustrated with couple examples:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">if (is_int($variable)) {<br>\n    \/\/ here we can be sure that $variable is integer<br>\n}<br>\n\/\/ using PHPUnit&#8217;s asserts<br>\nself::assertNotNull($variable);<br>\n\/\/ here we can be sure that $variable is not null<\/p>\n\n\n\n<p>Type-specifying extension cannot have&nbsp;<code><strong>PHPStan\\Analyser\\TypeSpecifier<\/strong><\/code>&nbsp;injected in the constructor due to circular reference issue, but the extensions can implement&nbsp;<code><strong>PHPStan\\Analyser\\TypeSpecifierAwareExtensio<\/strong>n<\/code>&nbsp;interface to obtain TypeSpecifier via a setter.<\/p>\n\n\n\n<p>This is the interface for type-specifying extension:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">namespace PHPStan\\Type;<br>\nuse PhpParser\\Node\\Expr\\StaticCall;<br>\nuse PHPStan\\Analyser\\Scope;<br>\nuse PHPStan\\Analyser\\SpecifiedTypes;<br>\nuse PHPStan\\Analyser\\TypeSpecifierContext;<br>\nuse PHPStan\\Reflection\\MethodReflection;<br>\ninterface StaticMethodTypeSpecifyingExtension<br>\n{<br>\n    public function getClass(): string;<br>\n    public function isStaticMethodSupported(MethodReflection $staticMethodReflection, StaticCall $node, TypeSpecifierContext $context): bool;<br>\n    public function specifyTypes(MethodReflection $staticMethodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes;<br>\n}<\/p>\n\n\n\n<p>And this is how you&#8217;d write the extension for the second example above:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">public function getClass(): string<br>\n{<br>\n    return \\PHPUnit\\Framework\\Assert::class;<br>\n}<br>\npublic function isStaticMethodSupported(MethodReflection $staticMethodReflection, StaticCall $node, TypeSpecifierContext $context): bool;<br>\n{<br>\n    \/\/ The $context argument tells us if we&#8217;re in an if condition or not (as in this case).<br>\n    return $staticMethodReflection-&gt;getName() === &#8216;assertNotNull&#8217; &amp;&amp; $context-&gt;null();<br>\n}<br>\npublic function specifyTypes(MethodReflection $staticMethodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes<br>\n{<br>\n    \/\/ Assuming extension implements \\PHPStan\\Analyser\\TypeSpecifierAwareExtension.<br>\n    return $this-&gt;typeSpecifier-&gt;create($node-&gt;var, \\PHPStan\\Type\\TypeCombinator::removeNull($scope-&gt;getType($node-&gt;var)), $context);<br>\n}<\/p>\n\n\n\n<p>And finally, register the extension to PHPStan in the project&#8217;s config file:<\/p>\n\n\n\n<p class=\"has-text-color has-background has-vivid-green-cyan-color has-very-dark-gray-background-color\">services:<br>\n    &#8211;<br>\n    class: App\\PHPStan\\AssertNotNullTypeSpecifyingExtension<br>\n    tags:<br>\n    &#8211; phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension<\/p>\n\n\n\n<p>There&#8217;s also an analogous functionality for:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>dynamic methods<\/strong>&nbsp;using&nbsp;<code><strong>MethodTypeSpecifyingExtension<\/strong><\/code>&nbsp;interface and&nbsp;<code><strong>phpstan.typeSpecifier.methodTypeSpecifyingExtension<\/strong><\/code>&nbsp;service tag.<\/li><li><strong>functions<\/strong>&nbsp;using&nbsp;<code><strong>FunctionTypeSpecifyingExtension<\/strong><\/code>&nbsp;interface and&nbsp;<code><strong>phpstan.typeSpecifier.functionTypeSpecifyingExtension<\/strong><\/code>&nbsp;service tag.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-button aligncenter is-style-squared\"><a class=\"wp-block-button__link has-background has-vivid-cyan-blue-background-color\" href=\"https:\/\/github.com\/phpstan\/phpstan\"><strong>Download<\/strong><\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line. Prerequisites [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":15773,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","fifu_image_alt":"PHPStan \u2013 PHP Static Analysis Tool \u2013 Discover Bugs In Your Code Without Running It","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[28],"tags":[488,2518,2524],"class_list":["post-6346","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kali","tag-bugs","tag-php","tag-phpstan"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>PHPStan - PHP Static Analysis Tool - Discover Bugs<\/title>\n<meta name=\"description\" content=\"PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PHPStan - PHP Static Analysis Tool - Discover Bugs\" \/>\n<meta property=\"og:description\" content=\"PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\" \/>\n<meta property=\"og:site_name\" content=\"Kali Linux Tutorials\" \/>\n<meta property=\"article:published_time\" content=\"2019-08-29T14:29:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png\" \/>\n<meta name=\"author\" content=\"R K\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png\" \/>\n<meta name=\"twitter:creator\" content=\"@CyberEdition\" \/>\n<meta name=\"twitter:site\" content=\"@CyberEdition\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"R K\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\"},\"author\":{\"name\":\"R K\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/#\/schema\/person\/69444b58b9e267a4cf08fceb34b6f6ad\"},\"headline\":\"PHPStan &#8211; PHP Static Analysis Tool &#8211; Discover Bugs In Your Code Without Running It\",\"datePublished\":\"2019-08-29T14:29:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\"},\"wordCount\":2837,\"publisher\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png\",\"keywords\":[\"Bugs\",\"PHP\",\"PHPStan\"],\"articleSection\":[\"Kali Linux\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\",\"url\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\",\"name\":\"PHPStan - PHP Static Analysis Tool - Discover Bugs\",\"isPartOf\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png\",\"datePublished\":\"2019-08-29T14:29:19+00:00\",\"description\":\"PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage\",\"url\":\"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png\",\"contentUrl\":\"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png\"},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/#website\",\"url\":\"https:\/\/kalilinuxtutorials.com\/\",\"name\":\"Kali Linux Tutorials\",\"description\":\"Kali Linux Tutorials\",\"publisher\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kalilinuxtutorials.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/#organization\",\"name\":\"Kali Linux Tutorials\",\"url\":\"https:\/\/kalilinuxtutorials.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kalilinuxtutorials.com\/wp-content\/uploads\/2025\/07\/Kali.png\",\"contentUrl\":\"https:\/\/kalilinuxtutorials.com\/wp-content\/uploads\/2025\/07\/Kali.png\",\"width\":272,\"height\":90,\"caption\":\"Kali Linux Tutorials\"},\"image\":{\"@id\":\"https:\/\/kalilinuxtutorials.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CyberEdition\",\"https:\/\/www.threads.com\/@cybersecurityedition\",\"https:\/\/www.linkedin.com\/company\/cyberedition\",\"https:\/\/www.instagram.com\/cybersecurityedition\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/#\/schema\/person\/69444b58b9e267a4cf08fceb34b6f6ad\",\"name\":\"R K\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/kalilinuxtutorials.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d3937c9687f2da11bc0a716404ff91779fe19ca115208dbf66167ad353aca5aa?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d3937c9687f2da11bc0a716404ff91779fe19ca115208dbf66167ad353aca5aa?s=96&d=mm&r=g\",\"caption\":\"R K\"},\"url\":\"https:\/\/kalilinuxtutorials.com\/author\/ranjith\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"PHPStan - PHP Static Analysis Tool - Discover Bugs","description":"PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/","og_locale":"en_US","og_type":"article","og_title":"PHPStan - PHP Static Analysis Tool - Discover Bugs","og_description":"PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.","og_url":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/","og_site_name":"Kali Linux Tutorials","article_published_time":"2019-08-29T14:29:19+00:00","og_image":[{"url":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","type":"","width":"","height":""}],"author":"R K","twitter_card":"summary_large_image","twitter_image":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","twitter_creator":"@CyberEdition","twitter_site":"@CyberEdition","twitter_misc":{"Written by":"R K","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#article","isPartOf":{"@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/"},"author":{"name":"R K","@id":"https:\/\/kalilinuxtutorials.com\/#\/schema\/person\/69444b58b9e267a4cf08fceb34b6f6ad"},"headline":"PHPStan &#8211; PHP Static Analysis Tool &#8211; Discover Bugs In Your Code Without Running It","datePublished":"2019-08-29T14:29:19+00:00","mainEntityOfPage":{"@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/"},"wordCount":2837,"publisher":{"@id":"https:\/\/kalilinuxtutorials.com\/#organization"},"image":{"@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage"},"thumbnailUrl":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","keywords":["Bugs","PHP","PHPStan"],"articleSection":["Kali Linux"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/","url":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/","name":"PHPStan - PHP Static Analysis Tool - Discover Bugs","isPartOf":{"@id":"https:\/\/kalilinuxtutorials.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage"},"image":{"@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage"},"thumbnailUrl":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","datePublished":"2019-08-29T14:29:19+00:00","description":"PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/kalilinuxtutorials.com\/phpstan-php-static-analysis-tool\/#primaryimage","url":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","contentUrl":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png"},{"@type":"WebSite","@id":"https:\/\/kalilinuxtutorials.com\/#website","url":"https:\/\/kalilinuxtutorials.com\/","name":"Kali Linux Tutorials","description":"Kali Linux Tutorials","publisher":{"@id":"https:\/\/kalilinuxtutorials.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kalilinuxtutorials.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/kalilinuxtutorials.com\/#organization","name":"Kali Linux Tutorials","url":"https:\/\/kalilinuxtutorials.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/kalilinuxtutorials.com\/#\/schema\/logo\/image\/","url":"https:\/\/kalilinuxtutorials.com\/wp-content\/uploads\/2025\/07\/Kali.png","contentUrl":"https:\/\/kalilinuxtutorials.com\/wp-content\/uploads\/2025\/07\/Kali.png","width":272,"height":90,"caption":"Kali Linux Tutorials"},"image":{"@id":"https:\/\/kalilinuxtutorials.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CyberEdition","https:\/\/www.threads.com\/@cybersecurityedition","https:\/\/www.linkedin.com\/company\/cyberedition","https:\/\/www.instagram.com\/cybersecurityedition\/"]},{"@type":"Person","@id":"https:\/\/kalilinuxtutorials.com\/#\/schema\/person\/69444b58b9e267a4cf08fceb34b6f6ad","name":"R K","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/kalilinuxtutorials.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d3937c9687f2da11bc0a716404ff91779fe19ca115208dbf66167ad353aca5aa?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d3937c9687f2da11bc0a716404ff91779fe19ca115208dbf66167ad353aca5aa?s=96&d=mm&r=g","caption":"R K"},"url":"https:\/\/kalilinuxtutorials.com\/author\/ranjith\/"}]}},"jetpack_featured_media_url":"https:\/\/1.bp.blogspot.com\/-Qtbf8fDwyR8\/XWYGi04HmxI\/AAAAAAAACPo\/sC6QyPiTk4wYnuN5jGHiERdZkU6QBu5rACLcBGAs\/s1600\/phpstan_1%2B%25281%2529.png","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":14866,"url":"https:\/\/kalilinuxtutorials.com\/bughound\/","url_meta":{"origin":6346,"position":0},"title":"Bughound : Static Code Analysis Tool Based On Elastic search","author":"R K","date":"July 21, 2021","format":false,"excerpt":"Bughound is an open-source static code analysis tool that analyzes your code and sends the results to Elasticsearch and Kibana to get useful insights about the potential vulnerabilities in your code. Bughound has its own Elasticsearch and Kibana Docker image that is preconfigured with dashboards to give you a strong\u2026","rel":"","context":"In &quot;Kali Linux&quot;","block_context":{"text":"Kali Linux","link":"https:\/\/kalilinuxtutorials.com\/category\/kali\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5295,"url":"https:\/\/kalilinuxtutorials.com\/recsech-footprinting-reconnaissance-web\/","url_meta":{"origin":6346,"position":1},"title":"Recsech &#8211; Tool For Doing Footprinting &#038; Reconnaissance On The Target Web","author":"R K","date":"June 11, 2019","format":false,"excerpt":"Recsech is a tool for doing\u00a0\u00a0Footprinting and Reconnaissance on the target web. It collects information such as DNS Information, Sub Domains, HoneySpot Detected, Subdomain takeovers, Reconnaissance On Github and much more you can \u00a0 Features In Tools Also Read - Finshir : A Coroutines-Driven Low & Slow Traffic Sender Requirements\u2026","rel":"","context":"In &quot;Kali Linux&quot;","block_context":{"text":"Kali Linux","link":"https:\/\/kalilinuxtutorials.com\/category\/kali\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":28437,"url":"https:\/\/kalilinuxtutorials.com\/sstimap\/","url_meta":{"origin":6346,"position":2},"title":"SSTImap : Penetration Testing Tool For SSTI Detection And Exploitation","author":"R K","date":"February 22, 2023","format":false,"excerpt":"SSTImap is a penetration testing software that can check websites for Code Injection and Server-Side Template Injection vulnerabilities and exploit them, giving access to the operating system itself. This tool was developed to be used as an interactive penetration testing tool for SSTI detection and exploitation, which allows more advanced\u2026","rel":"","context":"In &quot;Kali Linux&quot;","block_context":{"text":"Kali Linux","link":"https:\/\/kalilinuxtutorials.com\/category\/kali\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEihkEy2KrL1F8zB-FP9GrjAD5lclIEJ_ghuuYzXu43R_ULm5YLrxKIe_sKE3Az1UaRwKGsWv3xa_xAdMRX4Mb9iPYXOFGIRACu2ThkjOJCoInFvP6eK6J-xmVwihZtKYi9gOrUyC6Q50LCJFux6AnXRfeXFEaNEp0pyR4rz8JJ_6T4s3fNkXsPO2TlP\/s16000\/sstimap.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEihkEy2KrL1F8zB-FP9GrjAD5lclIEJ_ghuuYzXu43R_ULm5YLrxKIe_sKE3Az1UaRwKGsWv3xa_xAdMRX4Mb9iPYXOFGIRACu2ThkjOJCoInFvP6eK6J-xmVwihZtKYi9gOrUyC6Q50LCJFux6AnXRfeXFEaNEp0pyR4rz8JJ_6T4s3fNkXsPO2TlP\/s16000\/sstimap.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEihkEy2KrL1F8zB-FP9GrjAD5lclIEJ_ghuuYzXu43R_ULm5YLrxKIe_sKE3Az1UaRwKGsWv3xa_xAdMRX4Mb9iPYXOFGIRACu2ThkjOJCoInFvP6eK6J-xmVwihZtKYi9gOrUyC6Q50LCJFux6AnXRfeXFEaNEp0pyR4rz8JJ_6T4s3fNkXsPO2TlP\/s16000\/sstimap.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEihkEy2KrL1F8zB-FP9GrjAD5lclIEJ_ghuuYzXu43R_ULm5YLrxKIe_sKE3Az1UaRwKGsWv3xa_xAdMRX4Mb9iPYXOFGIRACu2ThkjOJCoInFvP6eK6J-xmVwihZtKYi9gOrUyC6Q50LCJFux6AnXRfeXFEaNEp0pyR4rz8JJ_6T4s3fNkXsPO2TlP\/s16000\/sstimap.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":6892,"url":"https:\/\/kalilinuxtutorials.com\/mosca-search-tool-bugs-grep-unix-command\/","url_meta":{"origin":6346,"position":3},"title":"Mosca : Manual Search Tool To Find Bugs Like A Grep Unix Command","author":"R K","date":"October 15, 2019","format":false,"excerpt":"Mosca is a manual analysis tool to find bugs like a grep unix command and since it is not dynamic the uses static code to search don't confuse with academic views hahaha don't have graph here or CFG which is a simple \"grep\" egg modules is a config to find\u2026","rel":"","context":"In &quot;Kali Linux&quot;","block_context":{"text":"Kali Linux","link":"https:\/\/kalilinuxtutorials.com\/category\/kali\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":9721,"url":"https:\/\/kalilinuxtutorials.com\/dirble\/","url_meta":{"origin":6346,"position":4},"title":"Dirble : Fast Directory Scanning And Scraping Tool","author":"R K","date":"March 17, 2020","format":false,"excerpt":"Dirble is a website directory scanning tool for Windows and Linux. It's designed to be fast to run and easy to use. How to Use? Download one of the\u00a0precompiled binaries\u00a0for Linux, Windows, or Mac, or compile the source using Cargo, then run it from a terminal. The default wordlist Dirble\u2026","rel":"","context":"In &quot;Kali Linux&quot;","block_context":{"text":"Kali Linux","link":"https:\/\/kalilinuxtutorials.com\/category\/kali\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":27320,"url":"https:\/\/kalilinuxtutorials.com\/scodescanner\/","url_meta":{"origin":6346,"position":5},"title":"SCodeScanner : Stands For Source Code Scanner Where The User Can Scans The Source Code For Finding The Critical Vulnerabilities","author":"R K","date":"September 28, 2022","format":false,"excerpt":"SCodeScanner stands for Source Code scanner where the user can scans the source code for finding the Critical Vulnerabilities. The main objective for this scanner is to find the vulnerabilities inside the source code before code gets published in Prod. Features Supported\u00a0PHP\u00a0LanguageSupported\u00a0YAML\u00a0LanguagePass results to bug tracking services like Jira also\u2026","rel":"","context":"In &quot;Kali Linux&quot;","block_context":{"text":"Kali Linux","link":"https:\/\/kalilinuxtutorials.com\/category\/kali\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhtJCxJETTAw64pgWkdHE7waqRucYKJNzSvXQcNWwxqpywBqTWrQp50CuumEm18vmB8mAUdD3hodnzKcKkfZ0VZuKlMt3QE4LiIBasXo54aQefOBMl_ogM0EjDa5FLuhd4zzRPMe4uhuMj26oygc_yQYI3aZCYw8aQwhSX5dRHcLvO1c1ZgZSLO0IFG\/s728\/a.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhtJCxJETTAw64pgWkdHE7waqRucYKJNzSvXQcNWwxqpywBqTWrQp50CuumEm18vmB8mAUdD3hodnzKcKkfZ0VZuKlMt3QE4LiIBasXo54aQefOBMl_ogM0EjDa5FLuhd4zzRPMe4uhuMj26oygc_yQYI3aZCYw8aQwhSX5dRHcLvO1c1ZgZSLO0IFG\/s728\/a.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhtJCxJETTAw64pgWkdHE7waqRucYKJNzSvXQcNWwxqpywBqTWrQp50CuumEm18vmB8mAUdD3hodnzKcKkfZ0VZuKlMt3QE4LiIBasXo54aQefOBMl_ogM0EjDa5FLuhd4zzRPMe4uhuMj26oygc_yQYI3aZCYw8aQwhSX5dRHcLvO1c1ZgZSLO0IFG\/s728\/a.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhtJCxJETTAw64pgWkdHE7waqRucYKJNzSvXQcNWwxqpywBqTWrQp50CuumEm18vmB8mAUdD3hodnzKcKkfZ0VZuKlMt3QE4LiIBasXo54aQefOBMl_ogM0EjDa5FLuhd4zzRPMe4uhuMj26oygc_yQYI3aZCYw8aQwhSX5dRHcLvO1c1ZgZSLO0IFG\/s728\/a.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/posts\/6346","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/comments?post=6346"}],"version-history":[{"count":0,"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/posts\/6346\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/media\/15773"}],"wp:attachment":[{"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/media?parent=6346"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/categories?post=6346"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kalilinuxtutorials.com\/wp-json\/wp\/v2\/tags?post=6346"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}