Technology

#How to Statically Analyse PHP Projects with PHPStan – CloudSavvy IT

“#How to Statically Analyse PHP Projects with PHPStan – CloudSavvy IT”

PHPStan logo

PHPStan is a static analysis system for PHP projects. It finds bugs in your codebase by inspecting the source files. You don’t need to run your code or manually write tests to discover issues!

The term “static analysis” is defined as debugging code without actually executing it. It’s most often used with interpreted languages, such as PHP, as the issues it finds tend to surface at the compilation stage in compiled languages.

Static analysis works best when run within a well-structured, strongly-typed codebase. This is particularly important in the case of PHPStan as it’s technically a hybrid analysis tool.

Contrary to our definition of static analysis, PHPStan will actually load and run your source files. This is because it partially utilises PHP’s built-in introspective capabilities to analyse your project.

Consequently, side effects at the root of the script will end up being executed:

function example() : void {
    echo "Example output";
}
 
example();

Were PHPStan to analyse the file shown above, you would observe Example output being emitted to the console. For this reason, it’s best to run PHPStan against inert source files (containing only classes and functions) which do not present side effects when loaded.

Adding PHPStan to Your Project

To run PHPStan, you’ll need to have PHP 7.1 or newer. This requirement only applies to the version of PHP used to execute PHPStan itself. The tool is capable of analysing source files targeting older versions of PHP.

It’s recommended you use Composer to add PHPStan as a dependency:

composer require --dev phpstan/phpstan

The PHPStan binary will be added to your project at vendor/bin/phpstan. You can now use it to analyse your codebase for the first time:

vendor/bin/phpstan analyse src

The command shown above will run PHPStan’s tests against all the source files in your src directory. Depending on the size of your codebase, this might take a few minutes to complete.

A successful PHPStan run

You’ll see a green “[OK] No errors” message if all the tests pass. Otherwise, the list of errors encountered will be displayed. Follow the guidance shown to resolve each error before re-running PHPStan.

Error Types and Levels

PHPStan includes a plethora of checks covering a wide variety of possible codebase issues. Some of the most common ones you’ll encounter include the following:

  • Type system issues – Assigning a typed property an invalid value, or passing incorrectly typed parameters to a method. This also includes contract issues, such as a class incorrectly implementing an interface.
  • Function invocations – Passing too many, or not enough, parameters when calling a function or method (e.g. 3 instead of 4).
  • Unknown classes, methods and functions – Trying to use something which doesn’t exist within the codebase.
  • Access to undefined/possiby undefined variables – Trying to use a variable that is not defined in a given scope, or that which may not always have a value but is used in a context where one is assumed.
  • Dead code checking – Flagging of useless code, such as boolean comparisons which will always resolve to the same value and code branches which will not never get executed (e.g. code following a return statement within functions).

Rules are sorted into 9 different “levels”, labelled from 0 to 8. The special level max acts as an alias for the highest possible level. Over time, PHPStan may add additional numerical levels, so using max ensures you always get the strictest possible checks.

A failed PHPStan run

By default, PHPStan executes level 0. This includes only the most fundamental of tests. It’s a good idea to get your codebase passing each level individually before advancing to the next one. Mature projects are likely to run into another set of issues with each new level.

To change the level PHPStan uses, you can pass the --level command line parameter:

vendor/bin/phpstan analyse src --level 8

In addition to the built-in checks, PHPStan extensions are available to add even more functionality. You can also write your own rules from scratch. This is useful when you’re deprecating functionality that developers should no longer use in any new code. We’ll cover creating custom rules in a future article.

Configuring PHPStan

Beyond initial experimentation, using PHPStan’s command-line interface can quickly become tiresome. It’s best to add a configuration file to your project which can then be committed to source control for all your developers to use.

PHPStan uses the Neon configuration file format, which has a syntax very similar to YAML. Create a phpstan.neon file in your project’s root directory. This file is automatically loaded whenever PHPStan starts, so you can now run the analyse command with no further arguments:

vendor/bin/phpstan analyse

To override the configuration file which is used, pass the --configuration flag:

vendor/bin/phpstan analyse --configuration /phpstan-config.neon

You now need to populate your phpstan.neon file with some content. A good starting point might look like this:

parameters:
  level: 0
  paths:
    - src

This basic configuration file should give the same output as the command-line invocation shown earlier. You can add additional directories to scan as new lines in the paths section. To exclude files and directories, add them to an excludes_analyse leaf within the same parameters section.

Ignoring Errors

Occasionally, PHPStan may surface an issue which is unavoidable. If there’s a problem which you cannot immediately address, you may wish to explicitly ignore it in order to allow the tests to pass.

This is particularly important when you want to move up to another level of checks, or you’re using PHPStan in a CI environment where a failed run will stop your build deploying. Even so, don’t take this course of action lightly – you should only choose to ignore a reported error if you’re certain it will be safe to do so.

Once you’ve made the decision, add a new ignoreErrors section within the parameters of your configuration file. You have to define the message to match, as a regex, and the paths to apply the exclusion to:

parameters:
  level: 0
  paths:
    - src
  ignoreErrors:
    - message: '/Return type string of method ExampleClass::example() is not covariant(.*).'
      path: src/ExampleClass.php

You can optionally specify paths as an array of paths, replacing the single path key shown above.

Optional Rules

PHPStan’s strictness can be adjusted by a series of configuration variables. These allow you to finetune the checks which are made, outside of the levels system described above. Some of these are potentially controversial or unlikely to align with all private style guides, hence they’re off by default.

A few settings which might be worth enabling include:

  • checkAlwaysTrueInstanceof – Flags uses of instanceof which will always evaluate to true.
  • checkAlwaysTrueStrictComparison – Flags when an expression using === or !== will always evaluate to true.
  • checkFunctionNameCase – Ensures the casing of function names matches their definition when called throughout the codebase.
  • polluteScopeWithLoopInitialAssignments – When set to false (it’s true by default), variables declared in initial loop statements (e.g. $i in $for ($i = 1; $i < 10; $i++)) are prevented from being accessed outside the loop’s code block, avoiding possible pollution of the parent scope.
  • reportStaticMethodSignatures – Enforces full type checking for parameters and return types in static methods when overridden by a child class.

Complete details on these optional settings – and many more – can be found within PHPStan’s configuration reference.

Conclusion

That’s the end of our introduction to PHPStan. It helps you have confidence in your codebase and highlights possible issues before they become a problem in production.

PHPStan is so quick to setup that there’s really no reason not to use it, especially when working with a modern strongly-typed codebase. Don’t be tricked into thinking it can replace manual testing though. PHPStan may boast a large assortment of checks but it cannot identify logical issues and does not understand your project’s business rules. It’s merely another asset in your toolbox when assessing a codebase’s health, serving alongside trusted companions such as unit tests and end-to-end functionality tests.

If you liked the article, do not forget to share it with your friends. Follow us on Google News too, click on the star and choose us from your favorites.

For forums sites go to Forum.BuradaBiliyorum.Com

If you want to read more like this article, you can visit our Technology category.

Source

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button
Close

Please allow ads on our site

Please consider supporting us by disabling your ad blocker!