DEV Community

Cover image for Setting up Vim for PHP and laravel in 2024
woland
woland

Posted on

Setting up Vim for PHP and laravel in 2024

I am going to mostly document my own journy of setting up Vim (Not Neovim!) for PHP and laravel. Feel free to follow along.

We're going to use Vim+VimPlug+CoC.nvim, so we need to have nodejs and npm installed. It goes without saying that you should have Vim8+ as well. The current version of Vim as of this writing is Vim-9.1

So let's start from a clean ~/.vimrc

Lets place this block, that automatically installs VimPlug, on top of our ~/.vimrc.

function! VimplugInstaller()
  let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
  if empty(glob(data_dir . '/autoload/plug.vim'))
    silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
    autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
  endif
endfunction

call VimplugInstaller()
Enter fullscreen mode Exit fullscreen mode

Followed by several essential plugins:

call plug#begin()

Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'https://github.com/preservim/tagbar.git'
Plug 'vim-php/phpctags', {'for':'php'}
Plug 'honza/vim-snippets'
Plug 'SirVer/ultisnips'
Plug 'tpope/vim-commentary'
Plug 'sheerun/vim-polyglot'
Plug 'jwalton512/vim-blade'

call plug#end()
Enter fullscreen mode Exit fullscreen mode

The most important one, is coc.nvim. The rest are for various enhancements, that we'll go over soon, but before we do, let's define some extensions for coc.nvim and configure the other plugins.

"===[Coc.nvim]==="
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#_select_confirm() : "\<C-g>u\<CR>"
" use <tab> to trigger completion and navigate to the next complete item
function! CheckBackspace() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction

inoremap <silent><expr> <Tab>
      \ coc#pum#visible() ? coc#pum#next(1) :
      \ CheckBackspace() ? "\<Tab>" :
      \ coc#refresh()
inoremap <expr><s-tab> coc#pum#visible() ? coc#pum#prev(1) : "\<c-h>"

" Enhanced <CR> for pairs
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
            \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"

" Disable < expansion for pairs
autocmd FileType * let b:coc_pairs_disabled = ["<"]

"===[ Coc-Explorer ]==="
" set up coc-explorer to open in the current directory
let g:coc_explorer_global_mirror = 0
let g:coc_explorer_disable_default_keybindings = 1
let g:coc_explorer_global_root = 'current'
nnoremap <space>e <Cmd>CocCommand explorer<CR>

"===[ Coc Global Extensions ]==="
let g:coc_global_extensions = [
  \ 'coc-html',
  \ 'coc-css',
  \ 'coc-pairs',
  \ 'coc-emmet',
  \ 'coc-explorer',
  \ 'coc-phpactor',
  \ 'coc-blade'
\ ]

" GoTo code navigation
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)

" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
"
" List code actions available for the current buffer
nmap <leader>ca  <Plug>(coc-codeaction)

nnoremap <silent> K :call ShowDocumentation()<CR>
function! ShowDocumentation()
  if CocAction('hasProvider', 'hover')
    call CocActionAsync('doHover')
  else
    call feedkeys('K', 'in')
  endif
endfunction

" Add `:Format` command to format current buffer
command! -nargs=0 Format :call CocActionAsync('format')
" Formatting selected code
vmap <leader>f  <Plug>(coc-format-selected)

" coc-pairs
" disable characters for a specified filetypes
autocmd FileType markdown let b:coc_pairs_disabled = ['txt']
Enter fullscreen mode Exit fullscreen mode

The above code, configures tab completion, auto pairs, coc-explorer file explorer and other keybinding to get the most out of coc.nvim.
In the coc global extension section, we define extensions to be installed automatically. I have decided to use phpactor, you may change it for coc-intelephense.

Lets also configure the snippets:

We can manage our snippets with coc.nvim too, but I choose to use UltiSnips for that.

"===[ SNIPPETS ]==="
"Use Ctrl j key to trigger the snippets, default was TAB but that conflicts with
"The Completion trigger see :h keycodes to change this to sth else 
"Use Ctrl j and k to move visually within the snippet that was just triggered
"Ctrl l lists the available snippets
let g:UltiSnipsExpandTrigger='<C-j>'
let g:UltiSnipsListSnippets='<C-l>'
let g:UltiSnipsJumpForwardTrigger='<C-j>'
let g:UltiSnipsJumpBackwardTrigger='<C-k>'
let g:copypath_copy_to_unnamed_register = 1
Enter fullscreen mode Exit fullscreen mode

Save and quit Vim and open it again and wait for the plugins and extensions to install.

If you get prompted by an error msg, just press enter and wait for the plugins and the extensions to install.

It's better to install the laravel extension manually:

:CocInstall @yaegassy/coc-laravel

Now lets configure the coc extensions.

Issue the :CocConfig command from Vim's command mode and paste the following, inside the file.

{
    "suggest.noselect": true,
    "explorer.icon.enableNerdfont": true,
    "explorer.file.reveal.auto": true
    "languageserver": {
        "phpactor": {
            "command": "phpactor",
            "args": ["language-server"],
            "trace.server": "verbose",
            "filetypes": ["php"]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

If you choose to use a local installation of phpactor, you can just remove coc-phpactor with :CocUninstall coc-phpactor and modify the ~/.vim/coc-settings.json to include a path to the phpactor executable and remove the languageserver block entirely.

{
    "phpactor.enable": true,
    "phpactor.path": "/usr/bin/phpactor",
}
Enter fullscreen mode Exit fullscreen mode

The keybindings:

The only keybindings that you should know, besides the usual Vim keybindings, are:

Key Action
Tab completion
gd definition
gy type definition
gi implementation
gr references
[g diagnostics prev
]g diagnostics next
ca code actions
K hover docs
f (in visual mode) format code
Ctrl-j Expand Snippet & Move to Next Placeholder
Ctrl+k Move to Prev Placeholder
Ctrl-l List Snippets
Space-e Open Explorer

Now we should have an efficient and comfortable setup for working with PHP and laravel.

Lets setup several other things for convenience

Theme:

Add these plugins to the plugins list and install them with :PlugInstall after sourcing the ~/.vimrc.

Plug 'ryanoasis/vim-devicons'
Plug 'catppuccin/vim', { 'as': 'catppuccin' }

Enter fullscreen mode Exit fullscreen mode

Setup Vim to use the popular catppuccin theme.

"===[ Theme ]==="
set background=dark
" Inspect $TERM instead of t_Co
if &term =~ '256color'
    " Enable true (24-bit) colors instead of (8-bit) 256 colors.
    if has('termguicolors')
        let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
        let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
        let &t_TI = ""
        let &t_TE = ""
        set termguicolors
        set mouse=a
        colorscheme catppuccin_mocha
    endif
    else
        colorscheme catppuccin_mocha
        let &t_TI = ""
        let &t_TE = ""
endif

if has('gui_running')
    set mouse=a
    set guicursor+=a:blinkon0
    set guifont=FiraCodeNerdFont\ 12
    colorscheme catppuccin_mocha
endif

"===[ Curosr Shape ]==="
let &t_SI = "\<Esc>[6 q"
let &t_SR = "\<Esc>[4 q"
let &t_EI = "\<Esc>[2 q"
Enter fullscreen mode Exit fullscreen mode

The above block, will make vim use termgui colors (in a termgui capable terminal) and use different cursor shapes for different modes.
Make sure your $TERM variable reports xterm-256color.

In the screenshot below, you can see phpactor, coc-explorer and tagbar at work.
I've left an error in the syntax to show you what the inline diagnostics look like.

Image description

It would do you well to familiarize yourself with the coc.nvim documentation and commands.

For example, running :CocDiagnostics will open a drawer with all the errors found by coc.nvim.

Image description

Pressing enter on each item will jump you to the line containing the error.

I could not find a decent phpdoc plugin for Vim, but besides that, this setup is very effective.

You can find my full config on github, (probably in the Devel branch) Woland's Vim

If you have any notes or questions, please leave a comment.

Where to go from here

Start using the setup and tweak it to your needs, little by little. This is not a drop and go config, it's just a kickstarter to put it plainly.

Some general notes:

  • Familiarize yourself with Vim's buffers.
  • NEVER :q Vim, unless you're done for the day
  • Learn about :vimgrep and :lvimgrep
  • Integrate fzf, ack, ag, rg into your workflow, (you need to quickly search large projects)

Possible Q&A

Can I use this with Nvim?
Yes, you just have to paste all the code into ~/.config/nvim/init.vim

Why not use Nvim with lspconfig and cmp etc ... ?
Because it takes way longer to configure and the results aren't better than what coc provides with so much ease.

Top comments (2)

Collapse
 
fred_functional profile image
Fred Functional

Thanks for the comprehensive guide on setting up Vim for PHP and Laravel! How do you think this setup compares to using an IDE like PHPStorm?

Collapse
 
woland profile image
woland

Your welcome.

compares to using an IDE like PHPStorm?

It doesn't! lol

PHPStorm is a great IDE except for the fact that it chews on your hardware until you have to close the program, besides, its closed source, expensive and proprietary. This setup is entirely free and perfectly useable, light and fast!