Joomla Developer Manual
Code check with PHPStan
This is a copy of a post by Hannes Papenburg in Mattermost. It will be here until a more complete version appears in the Manual.
There are of course several different ways to check your code with static analysers. I'm just going to explain how I'm doing it with phpstan right now.
How to automatically check your extensions code.
phpstan can easily be installed via composer with composer require --dev phpstan/phpstan in the root of your site or your repo. You can then call it with vendor/bin/phpstan (or vendor\bin\phpstan for Windows) on the CLI in the respective root. If you are developing an extension in a git repo, I would advise to have all your code in a subfolder like /src, so that you can keep all the dev tools, configurations and documentation in the root (or folders below the root) of your repo. If you are checking the extension inside a site installation, you can still do that, but it requires a bit more work. Besides the initial phpstan/phpstan package, I would advise to also install phpstan/phpstan-deprecation-rules (with composer require --dev phpstan/phpstan-deprecation-rules) as well to get all deprecated code.
phpstan can either be called with command line options or you can use a configuration file. I strongly recommend the later option and for the git repo solution described above, your config file could look like this:
includes:
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
parameters:
level: 0
paths:
- src
scanDirectories:
- joomla
ignoreErrors:
reportUnmatchedIgnoredErrors: false
What does this do? First of all, it includes the deprecation rules. Then it defines the strictness level, which currently is set to its lowest. You can raise that step by step and ideally you should reach level 5 at some point. It then defines the paths to check. If you follow the structure that I proposed above for a git repo, you only have to define the single /src folder here. If you are checking an extension installed inside a site, you would have to list all paths here, like components/com_test and administrator/components/com_test. Of course you only need those folders, which contain PHP code.
The next config option is then the information which additional folders to read for framework information. phpstan automatically reads the /vendor folder and with this option you can add additional code to this. In the above example, I copied a complete Joomla package into a subfolder /joomla of the repo and phpstan now can understand all references to classes in your code to that Joomla package. That way, you are teaching phpstan what all the Joomla core classes mean and do. At least in theory, because Joomla itself often enough is still struggling to provide code which a tool like phpstan can understand.
Now you can call vendor/bin/phpstan on your code and will get a list of all things phpstan doesn't understand, considers wrong or reads as deprecated. Now comes the fun part of going through that code to fix stuff or make phpstan better understand it. Now don't dismiss the part about making phpstan understanding your code better, because it isn't just phpstan which will better understand your code, but also both you and your IDE. It is quite a difference when all of a sudden you notice that the object you got from a function call actually already contains the code you need instead of having to re-invent this.
Methods to improve your code
The first one is of course to prevent magic code, which might return different stuff with different text input. All those $items = $this->get('Items'); in the views are horrible for this, because no analyser can find out what $this->get() actually returns. Avoid stuff like this where possible!
The second method is to typehint variables. If instead of $items = $this->get('Items');, you use $model = $this->getModel();$items = $model->getItems();, you can now typehint that $model is a Testeroo\Component\Site\Model\TestModel class by adding /** @var Testeroo\Component\Site\Model\TestModel $model */ somewhere in the file (preferably directly above the line where you are assigning $model).
The third method is typehinting return method parameters and return values in your code directly. If your method shouldn't return anything, mark it as returning void.
Which leads me to the fourth method and that comes into action when the typehinting capabilities of PHP are too limiting. In that case, you define those types in the docblocks.
Adding phpstan to your project is easy and a matter of minutes, while I also was able to find a lot of bugs that way. Please give it a try.