PHPStorm: Enabling code completion where there isn’t
When you just want to document “_
_magic" but you’re no “__magician”
I cannot start without mentioning the power the magic methods in PHP . Sometimes these help turn spaghetti code that looks like turd in a blender into expressive one liners because much of the heavy lifting is done in the these.
So, when you call a method that doesn’t exists, the
__call magic method will, for example, look into an array of anonymous functions is there is a method by the name, and return it, or execute something on other class.
This is the basic stone of the Macros capability in some Laravel classes. These Macros, which briefly translates into “inject this method into this class”, are used even for validating a request automatically, allowing the developer to use
This kind of magic is something PHPStorm doesn’t like.
You can see here the problem. When you start to type
$request, which is a Request class instance, PHPStorm won’t show you the
validate() method in the code completion list. This is for two reasons:
- There is no method
validate()because is injected as a Macro.
- The PHPDoc doesn’t exists in the Request class that
PHPStorm will tell you the method doesn’t exists and you should be careful, or that the class uses magic methods and won’t validate anything you call since it doesn’t know even if its correct or not. Hell, you could even chain two rows of fluent methods and you will never know if the whole chain is correct or not until you run your application:
Well, you wouldn’t unless you read the documentation. And you could document this in the code… but problem with files that do not belong to the project is very simple: you cannot edit them. I mean, you clearly can, but you shouldn’t under any circumstances, not even a single dot. Why is that? Because when you update your libraries you will lose any changes, and in the living ecosystem that is Packagist, you can’t count on something that will never be updated, thus overriding any type of changes.
Enter the metadata files
phpstorm.meta.php directory is a very handy, almost surprising, addition for your project. It allows to add, “override” and document classes and method that, for any reason, aren’t properly documented. Create it in the root directory of your project, use something like
mymetas.meta.php for your files and you’re set.
I will use the Request example to illustrate how we can add the method “injected” by Laravel that isn’t hinted anywhere in the code. We can just copy-and-paste the core method that it references, same with its PHPDoc, and we’re done.
Go to any project in your file, and boom. Next time you will have type-hinting in PHPStorm with that method included.
We can also add a property into the class. It’s very straightforward, just declare it like normal:
And next time, boom, also type-hinting for your property.
PHPStorm will also look into the PHPDocs of the class, so you can offer a duplicate method with alternative parameters and return types, or override a PHPDoc-declared method or property with another. Seems that declared methods and return types will prevail over any PHPDoc you set.
For big projects, the metadata files are a godsend, specially when the codebase is big and there are things that PHPStorm can’t pick easily, saving you the time to tests if what you typed actually works.
The manual way or the highway
Currently there is no way for PHPStorm to intelligently check for magic methods that are just more than simple. That means, you will have to add, override or document these to the metadata files manually. Additionally, you will have to turn off the “multiple classes declaration” in the “Undefined” inspections:
Disabling it will ease your mind when using the classes that are duplicated in the meta file, like the Request class we extended previously.
Clearly PHPstorm it’s not very intelligent when it comes to magic methods, and Jetbrains decided to not tackle this feature since who knows when, but at least the metadata exists to solve these problems in someway, until the developer team creates a way to understand magic.
PS: If you’re wondering what color pallete I’m using for my IDE, is Solarized Dark.