New .phpstorm.meta.php features
As you may know, besides built-in “code awareness” capabilities, PhpStorm also relies on external knowledge of code. This knowledge comes in the form of PHP stubs and the .phpstorm.meta.php file.
While stubs cover the Standard PHP Library components and common extensions, .phpstorm.meta.php is a special metadata file that you can use for extending the PhpStorm functionality, based on your own needs or project requirements. It is bundled as part of the stubs package (you can check the meta folder to locate it), but it can also be placed anywhere within your project. You can even create multiple metas – PhpStorm will collect and merge all the information from them.
In PhpStorm 2019.1, we’ve implemented several metadata features that may come in handy. Read this post for a detailed look into them.
Let’s start with writing a simple count function like this:
$total = count($array, ...)
If you invoke code completion for the second argument on the above piece of code, initially you’ll get a list of not-so-relevant constants:
In most cases, however, the second argument should be either the
COUNT_RECURSIVE constant, corresponding to the 0 and 1 integer values.
You can certainly type a couple of symbols to quickly locate the necessary constant. But shouldn’t there be a way to see them suggested in the first place as the most likely choices? This is where .phpstorm.meta.php comes into play.
In the .phpstorm.meta.php file, you can use the expectedArguments directive, which instructs PhpStorm that a certain function accepts a certain set of arguments.
To deal with our case, let’s add the following record to .phpstorm.meta.php:
expectedArguments(\count(), 1, COUNT_NORMAL, COUNT_RECURSIVE);
Here, we’ve specified the function we are working with, the zero-based index of the argument, and the actual set of expected values. Now, in our initial code piece, all we need to do is invoke code completion again – and the newly added values will be proposed at the very top of the suggestions list:
When adding your own entries, keep the following in mind:
- You need to provide the fully qualified name of the function or method so that PhpStorm resolves it correctly.
- You can enumerate expected arguments via the comma
,or the pipe
|bitwise operator. The former is used for functions expecting a single value out of the set of values, while the latter is used for functions expecting a bit mask of constants, such as json_encode.
Now for some real-world example.
Let’s say we are implementing a Console command based on the symfony/console component. Sometimes there will be arguments that we want to pass to our command. In this case, we’ll be implementing a
With expectedArguments in place, we could advise PhpStorm to expect the
InputArgument::* constants here. To do that, we should add the following line to .phpstorm.meta.php:
expectedArguments( \Symfony\Component\Console\Command\Command::addArgument(), 1, \Symfony\Component\Console\Input\InputArgument::OPTIONAL, \Symfony\Component\Console\Input\InputArgument::REQUIRED, \Symfony\Component\Console\Input\InputArgument::IS_ARRAY );
If we try autocompletion now, we’ll see the added constants in the suggestions list:
For some functions, the list of possible arguments’ values can be quite large. What’s more, different functions can accept the same sets of values. The ini_get and ini_set functions accepting the php.ini directives can serve as good examples.
Now, if we provide the list of expected arguments for each of these functions by using the above technique, the .phpstorm.meta.php file will grow excessively large. Even worse, it will contain duplicate data, and the amount of work required to maintain it will also double.
To handle this, .phpstorm.meta.php provides two directives, registerArgumentsSet and argumentsSet, which work as follows:
- registerArgumentsSet accepts two arguments: the arbitrary name of the set of arguments and the list of actual values contained in this set. Values are specified the same way as the list of expected arguments: depending on the function or method you are working with, you can enumerate them via the comma , or the pipe | bitwise operator.
To register the set of arguments for the above case, we simply specify the directive like this:
- Having registered the single set of arguments, we can reference it from within expectedArguments for both functions by using the argumentsSet directive:
expectedArguments(\ini_get(), 0, argumentsSet("ini_values"));
expectedArguments(\ini_set(), 0, argumentsSet("ini_values"));
Expected return values
With the expectedReturnValues directive, you can tell PhpStorm which values a certain function or method returns. The directive is specified similarly to expectedArguments: you provide it with a function and the set of actual values (you can register such sets via registerArgumentsSet, too, of course).
As soon as you do this, PhpStorm will provide code completion for function and static method calls in conditional statements:
Consider another real-world example.
Let’s say you are doing an HTTP request with one of the available PSR-7 compatible clients. As the result, you’ll get a $response object of a class that implements \Psr\Http\Message\ResponseInterface. Here you may want to check the status code and perform the suitable action. It turns out handy to instruct PhpStorm that ResponseInterface::getStatusCode() returns a set of HTTP status codes:
Please note that these features are currently experimental and under active development. Since they are in early access, we encourage you to give us your feedback and share what works for you and what you’d like added.
Just as with regular stubs, we will happily accept your GitHub pull requests for .phpstorm.meta.php. If you develop a framework or a library, you can supply it with its own metadata file, too. Add it to your package and with PhpStorm 2019.1 users will get desired autocompletion right away.
In the future, all these capabilities may be reimplemented via PHPDoc (for example, by enhancing the existing @param or @return tags). This could make the entire thing much easier to use and maintain, but naturally, it requires some standardization efforts in the first place. Should this happen at any point, don’t worry, we’ll provide the means of migrating your metas to PHPDoc.
Your JetBrains PhpStorm Team
The Drive to Develop