Setup Vim As PHP IDE

Posted on Categories programming

PHP VIM IDE

Background

Recently I am developing an app for Nextcloud, and it requires some PHP tool, usually, vscode is my go-to IDE/Editor for any small project. but I notice a drag on my 4 years old Dell-XPS laptop, so I decided to switch to vim. I have been a casual vim user, but this time I want to set up correctly, so here is how I do it:

Update: 2020-8-21 adding phan support: Setup vim with phan

Update: 2020-8-30 when php-language-server is initialized , it will scan the whole dirctory and if xdebug is enabled at the same time, it will take longer

Vim Components :

  • vim-gtk with python3 support
  • vim-plug as a plugin manager
  • ALE as language protocol client
  • PHP-language-server as a language server
  • deoplete.nvim for auto-completion
  • PHP-CS-Fixer for code standard compliance
  • autoformat for code format(Mainly for indenting)
  • vim-debug for code step by step debugging

Let’s start from an empty docker container to see how can we set it up

1 first install some basic tool

apt install git curl composer python3-pip

danny@xps:~$ docker run -i -t ubuntu /bin/bash
root@05ba32a655a8:/# apt update 
Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
.........
root@05ba32a655a8:/# apt install git curl composer python3-pip
Reading package lists... Done
Building dependency tree 

2 Install vim-gtk

apt install vim-gtk

root@05ba32a655a8:/# apt install vim-gtk
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
......

we are installing vim-gtk instead of plain vim is we need the vim python3 support which is needed by vim-debug. To check if your vim support python3,issue the following command:

root@05ba32a655a8:/# vim --version 
VIM - Vi IMproved 8.1 (2018 May 18, compiled Apr 15 2020 06:40:31)
Included patches: 1-2269
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge version with GTK3 GUI.  Features included (+) or not (-):
+acl               -farsi             -mouse_sysmouse    -tag_any_white
+arabic            +file_in_path      +mouse_urxvt       +tcl
+autocmd           +find_in_path      +mouse_xterm       +termguicolors
+autochdir         +float             +multi_byte        +terminal
-autoservername    +folding           +multi_lang        +terminfo
+balloon_eval      -footer            -mzscheme          +termresponse
+balloon_eval_term +fork()            +netbeans_intg     +textobjects
+browse            +gettext           +num64             +textprop
++builtin_terms    -hangul_input      +packages          +timers
+byte_offset       +iconv             +path_extra        +title
+channel           +insert_expand     +perl              +toolbar
+cindent           +job               +persistent_undo   +user_commands
+clientserver      +jumplist          +postscript        +vartabs
+clipboard         +keymap            +printer           +vertsplit
+cmdline_compl     +lambda            +profile           +virtualedit
+cmdline_hist      +langmap           -python            +visual
+cmdline_info      +libcall           +python3           +visualextra
...

if you can see +python3, then you are good to go.

3 install vim-plug for an easier plugin installation

Go to https://github.com/junegunn/vim-plug to see how you can do it. we are using vim8 here, not neovim, so we will issue following command:

curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

root@05ba32a655a8:/# cd
root@05ba32a655a8:~# curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
>     https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 80033  100 80033    0     0  77853      0  0:00:01  0:00:01 --:--:-- 77853

after installing vim-plug, we will set up the config for it in ~/.vimrc

call plug#begin('~/.vim/plugged')


call plug#end()

vim plugins will come between this two commnds

4 Install ALE

add Plug 'dense-analysis/ale' between the two lines:

call plug#begin('~/.vim/plugged')

Plug 'dense-analysis/ale'

call plug#end()

close and open .vimrc again and then type command PlugInstall, ALE will be installed

5 install php-language-server

composer global require felixfbecker/language-server jetbrains/phpstorm-stubs:@dev

root@05ba32a655a8:~# composer global require felixfbecker/language-server jetbrains/phpstorm-stubs:@dev
Changed current directory to /root/.composer
Using version ^5.4 for felixfbecker/language-server
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 17 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-ctype (v1.18.1): Downloading (100%)         
  - Installing webmozart/assert (1.9.1): Downloading (100%)         
  - Installing webmozart/path-util (2.3.0): Downloading (100%)         
  - Installing webmozart/glob (4.1.0): Downloading (100%)         
  - Installing sabre/uri (2.2.0): Downloading (100%)         
  - Installing sabre/event (5.1.0): Downloading (100%)         
  - Installing psr/log (1.1.3): Downloading (100%)         
  - Installing phpdocumentor/reflection-common (2.2.0): Downloading (100%)         
  - Installing phpdocumentor/type-resolver (1.3.0): Downloading (100%)         
  - Installing phpdocumentor/reflection-docblock (4.3.4): Downloading (100%)         
  - Installing netresearch/jsonmapper (v1.6.0): Downloading (100%)         
  - Installing microsoft/tolerant-php-parser (v0.0.22): Downloading (100%)         
  - Installing jetbrains/phpstorm-stubs (dev-master 147255f): Cloning 147255f02e from cache
  - Installing felixfbecker/language-server-protocol (v1.4.0): Downloading (100%)         
  - Installing felixfbecker/advanced-json-rpc (v3.1.1): Downloading (100%)         
  - Installing composer/xdebug-handler (1.4.2): Downloading (100%)         
  - Installing felixfbecker/language-server (v5.4.6): Downloading (100%)         
Writing lock file
Generating autoload files
2 packages you are using are looking for funding.
Use the composer fund command to find out more!

Here we are using the global config, so all the php modules will be installed in the user .composer dir. As you can see from the composer output

Changed current directory to /root/.composer

on the github README, it does not mention the phpstrom-stubs, and you need to include it in the command, otherwise, you will get the following error:

composer global require felixfbecker/language-server
Changed current directory to /root/.composer
Using version ^5.4 for felixfbecker/language-server
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - felixfbecker/language-server v5.4.6 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - felixfbecker/language-server v5.4.5 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - felixfbecker/language-server v5.4.4 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - felixfbecker/language-server v5.4.3 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - felixfbecker/language-server v5.4.2 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - felixfbecker/language-server v5.4.1 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - felixfbecker/language-server v5.4.0 requires jetbrains/phpstorm-stubs dev-master -> satisfiable by jetbrains/phpstorm-stubs[dev-master] but these conflict with your requirements or minimum-stability.
    - Installation request for felixfbecker/language-server ^5.4 -> satisfiable by felixfbecker/language-server[v5.4.0, v5.4.1, v5.4.2, v5.4.3, v5.4.4, v5.4.5, v5.4.6].


Installation failed, deleting ./composer.json.

after installing the php-language-server, we need to generate the stubs for PHP

composer run-script --working-dir=/root/.composer/vendor/felixfbecker/language-server parse-stubs

root@05ba32a655a8:~#  composer run-script --working-dir=/root/.composer/vendor/felixfbecker/language-server parse-stubs
> LanguageServer\ComposerScripts::parseStubs
......
Saving Index
Finished
root@05ba32a655a8:~# 

now let’s configure php-language-server for ALE

call plug#begin('~/.vim/plugged')

Plug 'dense-analysis/ale'

call plug#end()


let g:ale_php_langserver_executable = '/root/.composer/vendor/bin/php-language-server.php'
let g:ale_linters = {'php': ['langserver']}
to check the php-language-server, you can type in ALEInfo to check the configuration and sometimes ALE will inform you which variable you should use to configure the linter and fixer

to see if the php-language-server is working or not, let’s create a simple PHP file to test, as you can see if we add invalid code or remove trailing ;, we will get error and move to the error line, you can see the message displayed on the bottom, remove error, the error message and mark also disapper

6 Install deoplete.nvim

you can go to the github and choose the the plugins you need , since i am using vim8 , here is my .vimrc config

call plug#begin('~/.vim/plugged')

Plug 'dense-analysis/ale'

Plug 'Shougo/deoplete.nvim'
Plug 'roxma/nvim-yarp'
Plug 'roxma/vim-hug-neovim-rpc'

call plug#end()

let g:ale_php_langserver_executable = '/root/.composer/vendor/bin/php-language-server.php'
let g:ale_linters = {'php': ['php', 'langserver']}

close and reopen .vimrc , then same command to install the plugin PlugInstall

deoplete.nvim will also need pynvim, let’s install it :

pip3 install pynvim

to enable deoplete.nvim, you need to add these two lines to .vimrc

let g:deoplete#enable_at_startup = 1
call deoplete#custom#source('ale', 'rank', 999)

and also set the .vimrc encoding by adding :

set encoding=utf-8

the final one would be :

set encoding=utf-8

call plug#begin('~/.vim/plugged')

Plug 'dense-analysis/ale'

Plug 'Shougo/deoplete.nvim'
Plug 'roxma/nvim-yarp'
Plug 'roxma/vim-hug-neovim-rpc'

call plug#end()

let g:ale_php_langserver_executable = '/root/.composer/vendor/bin/php-language-server.php'
let g:ale_linters = {'php': ['php', 'langserver']}

let g:deoplete#enable_at_startup = 1
call deoplete#custom#source('ale', 'rank', 999)

7 Install PHP-CS-Fixer

php-cs-fixer will help you write standard compliance code , here is an brife introduction on youtube : How to auto format your code

add these two lines to your .vimrc after installing php-cs-fixer by running composer global require friendsofphp/php-cs-fixer

let g:ale_fixers = {'php': ['php_cs_fixer'] }
let g:ale_php_cs_fixer_executable='/root/.composer/vendor/bin/php-cs-fixer'

let’s see how it works. on PHP standard , you should put { of a function on a new line, php-cs-fixer can automatically correct this one for you

8 Install vim-debug

we will make another post on how to configure the vim-debug


Leave a Reply

Your email address will not be published. Required fields are marked *