Improving IntelliSense for Laravel projects
Laravel has a lot of "magic" to help provide a developer-friendly framework. This "magic" can also be a roadblock for many IDE's to provide good IntelliSense suggestions. Here's how to fix that.
It is well known that Laravel works in magical ways to be a developer-friendly framework and make it super easy for you to bootstrap your ideas to fruition with as little friction as possible. With all that magic, though, comes the difficulty for your code editor to provide meaningful IntelliSense suggestions. Here’s how to fix it.
The example project
To illustrate what we're dealing with and progress looks like in solving the IntelliSense issues for Laravel projects, I have created a dummy project to showcase a few simple examples.
This very fictitious and a pretty standard project has the default App\User
model which has a couple of extra relationships:
- A
User
has many forumThread
s through->threads()
relationship; - A
Thread
belongs to an owner userUser
through->owner()
; - a
Thread
has manyPost
s by various users through->posts()
relationship.
We also have a SearchService
for the sake of illustrating some parts other than just model relationships. Bear with me.
The examples I'll give will be from various ThreadsController
methods to illustrate different kinds of missing IntelliSense and how it's solved later on.
The example code editor
For this example I will be using Visual Studio Code. With no support for Laravel out of the box and VS Code being one of the most popular code editors makes it the perfect choice for this article.
What it looks like at the very beginning
On a fresh VS Code install, you'll most likely notice that even the most basic IntelliSense for PHP is missing. It does not even find the related class that's part of the project.
Let's fix that.
PHP Intelephense
Open up your VS Code Extensions tab and search for PHP Intelephense. It's a fast and powerful code IntelliSense provider for your PHP language files. It is by far much faster than other alternatives you'll find on the VS Code Extension marketplace. Go ahead and install it.
Once installed, it's going to start indexing the project (searching for PHP classes, methods, symbols, etc) so it can have a better understanding of the project's structure as well as making it super fast.
Let's look at where it gets us!
We're now getting some help from VS Code! IntelliSense now recognises the existing Thread
and ThreadsController
classes and bumps them up to the top as the most relevant - in which case, they are! Once I select the first result and press <Enter>, it will automatically import the use App\Thread
statement at the top as well. Helpful!
There's something missing
Now let's try to use some relationships.
Looking at the code here we know clearly that the $thread->owner
relationship returns a User
model, but the PHP Intelephense extension can't yet make sense of that. It has no idea that trying to access owner
as a property on a Laravel's Model instance will actually fallback to the owner()
method on the instance, resolve the actual relationship, fetch the data from the database, and return a new instance of the related model. That's a lot of Laravel's magic in one place.
Let's look at another example. Let's resolve the SearchService class using the Laravel's Service Container:
We can see that the SearchService
has two methods: findPosts()
and findThreads()
- none were suggested after resolving the service from the Service Container. How can we fix that?
Laravel IDE Helper
Barryvdh is a legendary contributor to the Laravel community and Open Source in general. You are most likely using at least one of his open source packages already, such as Laravel Debugbar or Laravel CORS.
To help us today with the IntelliSense problems we have been experiencing, we will be installing another one of Barry's legendary packages - Laravel IDE Helper.
First, let's install it via Composer:
$ composer require --dev barryvdh/laravel-ide-helper
Next, we will need to run a few commands to generate a few helper files. These will help by providing more information to IntelliSense for it to understand more of the Laravel's magic. Let's run these commands:
$ php artisan ide-helper:generate
$ php artisan ide-helper:meta
$ php artisan ide-helper:models --nowrite
If all went well, you will now have three new files in your project's root:
- _ide_helper.php
- .phpstorm.meta.php
- _ide_helper_models.php
With any luck, PHP Intelephense will look at these files immediately and begin indexing the classes and methods available in your project. Let's see what that gets us.
That's better. Now accessing a relationship as a property returns the appropriate model. What about the Service Container?
Much, much better. IntelliSense recognises the class instance being returned from the app()
helper method is now the SearchService
and it correctly suggests the available methods on this class.
We have gone from no suggestions at all - to meaningful suggestions. This makes for a much faster and a more enjoyable coding experience while working on a Laravel project using Visual Studio Code. All thanks to the PHP Intelephense extension and the Laravel IDE Helper package!
Cleaning up
It can be a little tedious to constantly re-generate these helpers files in order to keep up with new changes, especially when working in a large team. Let's make it better.
.gitignore
First, let's add these files to your .gitignore
so they're not committed to the project's repository. There is no need to have these helper files as part of the repository because it will definitely pollute your Pull Requests will changes to these helper files and nobody likes the extra unrelated code in a PR.
_ide_helper.php _ide_helper_models.php .phpstorm.meta.php
Composer hook
Another way to automatically update the helper files is to call the IDE Helper commands automatically after Composer updates. Just insert this into your "scripts"
array in your composer.json
file:
"scripts":{ "post-update-cmd": [ "Illuminate\\Foundation\\ComposerScripts::postUpdate", "@php artisan ide-helper:generate", "@php artisan ide-helper:meta", "@php artisan ide-helper:models --nowrite" ], "post-install-cmd": [ "@php artisan ide-helper:generate", "@php artisan ide-helper:meta", "@php artisan ide-helper:models --nowrite" ] },
Now whenever you install or update your Composer packages, the helper files be automatically re-generated. Because these files are now also ignored by Git, there is no harm in constantly updating them.
As an added bonus, your colleagues will automatically get these helpers as well and their IDEs will pick up on them to make their development experience better as well! How cool is that :)
I hope this has helped. If you do have issues with the Laravel IDE Helper package, please refer to it's documentation here.