Microsoft has come a long way in recent years with tech like Windows Subsystem for Linux (WSL) and Visual Studio Code. The official Laravel docs now even favor WSL over alternatives like Vagrant. But while the Laravel docs give you enough to get up and running, they do not give you any guidance on how to set up VS Code for the best possible experience. Without some very important extensions and packages, you will find yourself constantly flipping between your editor, doc pages, error stacks, and terminal windows. Trying to keep everything in your head – Laravel syntax, artisan commands, phpunit tests, project structure, and so on – can be a significant cognitive burden which slows you down and pulls you out of your dev flow.

In this post, I will show how I set up VS Code to streamline Laravel development. The goal is to reduce as much as possible the need to look things up, manually run commands, or parse through arcane error messages.

GitHub - akmolina28/laravel-vscode-example: Laravel starter project pre-configured for VSCode (WSL2)
Laravel starter project pre-configured for VSCode (WSL2) - GitHub - akmolina28/laravel-vscode-example: Laravel starter project pre-configured for VSCode (WSL2)

Some of the highlights:

  • Full intellisense and autocomplete for Laravel framework, including Facades, Eloquent, and custom model classes.
  • "Quick fixes" to automatically fix common syntax errors.
  • Automatic code formatting according to predefined standards.
  • Snippets to generate commonly used code blocks.
  • Code navigation, quickly jump from caller to declaration.
  • ESLint and Hot Module Reloading (HMR).
  • Integrated Bash shell.
  • Inline Git history/blame.
  • Shortcuts and palette commands for PHPUnit, Artisan, and more.

Installing WSL2

The first thing you should do is install Windows Subsystem for Linux (WSL). Even if this is the only advice you take from this post, just install WSL and start playing with it. WSL has completely changed the way I develop in Windows, as it finally provides a really fast and robust way to run Linux distributions.

What is Windows Subsystem for Linux
Learn about the Windows Subsystem for Linux, including the different versions and ways you can use them.

I am using Ubuntu 20.04, but any distro that supports Docker would work. If you are new to WSL, here are two things to help get you started after you install your distro of choice:

  1. You can start up a shell from the Start Menu by typing the name of your distro. From a Windows point-of-view, WSL looks like any other App. You may need to run as Administrator for all features to work properly.
Launching WSL2 from the Start Menu

2. The WSL file system is mounted as virtual drive which you can access with the file explorer at \\wsl$

Visual Studio Code Remote Development

Next, install VS Code if you haven't already, and make sure you have the Remote Development extension. Unlike Visual Studio which uses Solution files and Project files to organize projects, Visual Studio code uses workspace folders. You simply open a folder from your file system, and that becomes your workspace in VS Code.

Developing in the Windows Subsystem for Linux with Visual Studio Code
Using Visual Studio Code Remote Development with the Windows Subsystem for Linux (WSL)

Remote Development is a very powerful, first-party extension which allows you to open workspaces on remote machines over SSH, or within WSL or Docker containers. VS Code will automatically run a server within your WSL instance, giving it full access to the Linux terminal and file system.

Docker Desktop and Laravel Sail

The next dependency is Docker Desktop for WSL2. Docker allows you to run Laravel Sail, a portable development environment which uses containers to run all of Laravel's dependencies like php, mysql, and redis. This saves you from having to manage all of those dependencies yourself, and it makes your development environment portable.

Install Docker Desktop on Windows
How to install Docker Desktop for Windows

Once Docker is installed and running, follow the Laravel documentation to set up Sail.

Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.
$ curl -s https://laravel.build/laravel-vscode-example | bash

$ cd laravel-vscode-example

$ ./vendor/bin/sail up -d

$ code .

The final command above will start VS Code in your WSL workspace. You should also be able to view the website at http://localhost/.

Laravel application default page

This is the bare minimum to get started with Laravel development on Windows, and this is where you can start bringing in more extensions to make working in VS Code much more efficient.

Scaffolding with Laravel Breeze

Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.

This is an optional step which I am including in order to have a more fully-fledged project to work with. Laravel Breeze will scaffold up a basic application with authentication and and user dashboard, plus it will install a front-end framework (I am using Vue.js in this example). Breeze will also configure Hot Module Reloading (HMR) which is critical for rapid front-end development.

Note that you can now use the WSL terminal in VS Code! Open the terminal with Ctrl+`.

Installing Laravel Breeze using the WSL terminal in VS Code
$ sail composer require laravel/breeze --dev

$ sail artisan breeze:install vue

$ sail artisan migrate

$ sail npm install

$ sail npm run dev

The final command above will start the Vite development server which serves up all of the client side assets. You should see some output in the console with links to where the site is running (Ctrl+click to open).

Laravel Vite

As of the time I am writing this, there are two issues that aren't addressed in the official documentation for Sail users on Windows.

  1. The default APP_URL will not be accessible because Windows cannot resolve it. You can either edit the hosts file to point APP_URL to 127.0.0.1, or you can change the APP_URL setting in your .env file to http://localhost. I prefer the latter approach.
  2. When using Sail, Vite will try to serve assets from 0.0.0.0, which will not resolve outside of the Docker containers. To fix this, manually configure the host for HMR in vite.config.js.
export default defineConfig({
    server: {
        hmr: {
            host: 'localhost',
        },
    },
    // ...
});

Vite should automatically restart after saving the files above, giving you a new link which should open now. Make sure you can also access the routes that were added by Breeze like /register and /login.

Laravel Breeze Register page

While the Register page is open, go to the file resources/js/Pages/Auth/Register.vue and make a small change. For example, change "Confirm Password" to "Re-type Password". As long as Vite is still running, you should see your changes instantly in the browser.

Test and Build Tasks

Now that Sail is up and running, we can configure the default Tasks for running Vite. While you can easily run these tasks manually in the terminal, I prefer the convenience of using hotkeys rather than switching to the terminal and running a sail command.

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Run Laravel",
      "type": "shell",
      "command": "./vendor/bin/sail npm run dev",
      "group": {
        "kind": "test",
        "isDefault": true
      },
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    },
    {
      "label": "Build for Production",
      "type": "shell",
      "command": "./vendor/bin/sail npm run build",
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}
.vscode/tasks.json

After adding the tasks.json file to the project, you can open the command palette with ctrl+shift+P and...

  • Type "Run Test Task" to start Laravel test container, or
  • Type "Run Build Task" to build for production

You can also set up keyboard shortcuts to access these commands more quickly.

[
  {
    "key": "ctrl+shift+r",
    "command": "workbench.action.tasks.test"
  },
  {
    "key": "ctrl+shift+b",
    "command": "workbench.action.tasks.build"
  }
]
keybindings.json

Extensions for PHP and Laravel

Visual Studio code comes with very little PHP support out of the box. You get basic syntax highlighting and some auto-complete support. Open any PHP file and write some code, and you'll quickly see how limited these features are.

No autocomplete for basic Laravel library functions

PHP Intelephense

The first extension to grab is PHP Intelephense, a feature-rich PHP language server which juices up VS Code's syntax highlighting and code navigation.

Quick fix for missing use statement

Right away you should see that errors are highlighted in the editor and in the explorer. There are also many "Quick fixes" available for common issues like missing imports. Intelephense can also format your code according to the latest PSR standards. I recommend turning on Format on Save.

laravel-ide-helper

Now we have a good backbone for PHP, but we lack support for Laravel development. This problem is not unique to VS Code, and there is actually a composer package to fix it.

$ sail composer require --dev barryvdh/laravel-ide-helper

$ sail artisan ide-helper:generate

$ sail artisan ide-helper:models

These artisan commands will generate PHPDocs for everything in Laravel. Now, Intelephense should give you full autocomplete for almost everything you need to do in php.

Full intellisense for Laravel

Intellisense for User-generated code

If you want intellisense for your own code, you will need to correctly decorate your functions and classes with PHPDocs. This is not very well documented in the PHP Intelephense docs, but there is a snippet available to do most of the work for you. If you type /** and press enter above a declaration, Intelephense will set up the PHPDoc with blanks for you to fill in and tab through (use the tab key).

Example PHPDoc

Once your PHPDoc is filled out, you should the info reflected by intellisense.

Intellisense for user-generated code

Laravel Artisan

While you can use the terminal to run artisan commands (e.g. sail artisan make:model MyModel), the Laravel Artisan extension makes life easier by adding commands to the command palette. Each command's options are explicitly shown, for example when you create a model, the extension will ask if you also want to create a factory, a seeder, a controller, and so on. You can (and should) also assign keyboard shortcuts to frequently used commands, like migrate or cache:clear.

To make this extension work with Sail, add two settings to your workspace:

{
  "artisan.docker.command": "./vendor/bin/sail",
  "artisan.docker.enabled": true,
}
.vscode/settings.json

Laravel Extension Pack

Laravel Extension Pack is a package of several extensions which are useful for Laravel development. Along with Laravel Artisan, it includes several extensions for snippets and blade support. I recommend looking at the list of included extensions and manually installing whichever seem useful for your project. For example, I prefer Vue/React for my view layer, so I do not bother with Blade extensions.

Extensions for Vue and JavaScript

Now that PHP is set up, we need support for our JavaScript framework. If you open a Vue file, right away you will notice that VS Code has no out-of-the-box support for Vue.js. First we will grab an add-on for language support, followed by additional addons for snippets, code formatting, and linting.

Vue.js file with no language support (formatted as Plain Text)

Volar

Volar is the standard extension for vue 3 (for Vue 2, check out Vetur). The extension reads the jsconfig.json file that ships with Laravel 9, so no additional configuration should be needed. Once installed, you should have syntax highlighting and basic intellisense.

Vue.js file with Volar language support

Prettier and ESLint

Now that we have language support, we can bring in extensions for code formatting and style enforcement. Prettier is a code formatter with support for Vue.js, and ESLint is the standard tool for linting JavaScript code and enforcing code standards. Together, these plugins can detect syntax and style errors, and offer quick fixes for common issues. In my opinion, these are must-have plugins for Vue.js development.

Prettier and ESLint require a few additional dependencies:

$ sail npm install prettier@^2.5.1 --save-dev

$ sail npm install eslint@^8.7.0 --save-dev

$ sail npm install vue-eslint-parser@^8.0.0 --save-dev

$ sail npm install eslint-plugin-vue --save-dev

$ sail npm install eslint-config-prettier --save-dev

$ sail npm install vite-plugin-eslint --save-dev

$ echo {}> .prettierrc.json

$ touch .eslintrc.json

$ touch .eslintignore

Then, edit .eslintrc.json as follows:

{
  "root": true,
  "extends": [
    "eslint:recommended",
    "plugin:vue/vue3-recommended",
    "prettier"
  ],
  "rules": {
    "vue/multi-word-component-names": "off"
  }
}

Next, edit .eslintignore to ignore vendor scripts and autogenerated files:

node_modules
public
vendor
**/dist
**/components.d.ts
!/docs/.vitepress
resources/js/ziggy.js

Finally, add ESLint to the Vite config so that lint errors are detected and displayed on the development server:

import eslint from "vite-plugin-eslint";

export default defineConfig({
  plugins: [
    eslint(),
  ],
});
Snippet from vite.config.js

Now, when you open a Vue or JavaScript file, VS Code should highlight syntax errors and warnings in your code. When you save the file, Prettier should automatically format it to comply with the lint rules. Any issues that cannot be fixed by the formatter can either be fixed by the "Quick fixes", or otherwise must be fixed by hand. ESLint will also run when the Vite build runs, and you will see any errors and warnings rendered in the browser as well as the terminal.

Vue VSCode Snippets

For Vue development, Vue VSCode Snippets is a must-have extension which offers tons of help when you can't remember syntax, and boilerplate templates to fill out new components.

PHPUnit Extensions

If you are doing Laravel right, you are writing tests for all of your new modules. Sail includes a solid implementation of PHPUnit, but you are still required to run your tests manually in the terminal. VS Code fortunately has several community extensions for running PHPUnit tests in a more seamless way. I prefer the extension PHPUnit for ease of configuration.

After installing, you will have to configure it to use Sail.

{
  "phpunit.command": "./vendor/bin/sail",
  "phpunit.paths": {
    "${workspaceFolder}": "/var/www/html"
  },
  "phpunit.phpunit": "test"
}
.vscode/settings.json

Now you can use the command palette to run your test suites. You can also run individual tests based on the position of your cursor. You should consider setting up keyboard shortcuts so you can easily run the test you are currently working on. These shortcuts will save you from having to manually run tests in the terminal, which can be very tedious and disruptive to your workflow.

[
  {
    "key": "ctrl+alt+t",
    "command": "phpunit.Test",
    "when": "editorFocus"
  },
  {
    "key": "ctrl+shift+alt+t",
    "command": "phpunit.TestSuite"
  }
]
keybindings.json
Unit test executed from editor focus hotkey

PHP Debugging

The latest version of Sail now includes Xdebug, making it easier than ever to set up native PHP debugging in VS Code. The PHP Debug extension allows you to set breakpoints and evaluate your variables and call stacks during runtime. The Debug Console also allows you to run PHP statements using the debugger's context.

  1. Add new value to .env
SAIL_XDEBUG_MODE=develop,debug
.env

2. Add

Other Useful Extensions

If you are new to VS Code, make sure to check out other popular extensions on the marketplace. Here are some other recommendations which I use in all of my projects, not just Laravel:

Thank you for reading! Feel free to post any questions or issues to Github.