After spending a few hours trying to make chained methods in PHP arrange itself below one and each other in a tidy manner, I have finally found a solution. In other words, on a file save I wanted to go from this:
$this->user->account->organizations()->saveMany(Organization::factory(5)
->make())->first()->update(['name' => 'A Big Brand Name']);
To something resembling this:
$this->user->account
->organizations()
->saveMany(Organization::factory(5)->make())
->first()
->update(['name' => 'A Big Brand Name']);
The above is clearly easier to read and thus it takes less time to understand what the code does.
What did not work for me
Here are a few various possibly unrelated methods to deal with the problem that did not work, in no particular order.
coc-prettier
I use coc-prettier in my current neovim setup, especially for it's ease of use on Markdown (prose-wrap anyone?) and Javascript. PHP is however not supported by prettier out of the box, and is rather supplied as a community maintained plugin under prettier/plugin-php.
Currently it looks like
these two do not play along.
The response is fairly recent and there is definitely a potential for
prettier plugins under coc-prettier
, sadly I could not find anything more
on the topic.
Intelephense in coc-phpls wit coc-prettier
In conjunction with the coc-prettier
above,
coc-phpls can do PHP formatting
on save as well with these two relevant settings in :CocConfig
below:
"intelephense.format.enable": true,
"coc.preferences.formatOnSaveFiletypes": ["php"]
Sadly, at the time of writing, the only formatter configuration option is
intelephense.format.braces
. This setting has no effect on aligning
chained PHP methods. It also somehow conflicts with prettier's tabWidth
if the hard-coded Intelephense value is different. I ended up
removing/turning off both above options.
vim-phpfmt
I've had absolutely no luck with the vim-phpfmt plugin whatsoever in regards to aligning chained methods in a PHP code. It could be expected as the plugin was not updated for more than a 5 years.
It utilizes phpcbf
called the PHP Code Beautifier and Fixer from
PHP CodeSniffer package
which is under active development. I believe this approach could work, but
I am not sure how long would it take to get it to work.
inotifywait script
At one point I tried to utilize the test watcher script by running globally installed prettier on the changed file, since I already had it up and running:
#!/bin/bash
while true; do
FILE=$(inotifywait --recursive \
--exclude=".*.*sw*" --exclude="4913" \
./watch_this_folder --format "%w%f" -e close_write)
&& clear
&& prettier --parser=php -w "$FILE"
done
But I had numerous issues with this approach ranging from delayed tests, through vim not re-rendering reformatted file to random file or even entire folders being reformatted on a short notice, so I did not continue down this path.
What works
There are two solutions I found are working reasonably well for aligning chained methods in PHP, both relying on prettier.
prettier/plugin-php vimscript
The modified vimscript I wrote about yesterday worked and I thought I stick with it. Go take a look over there for more details about the approach.
vim-prettier
I had no luck with the elaborate solution outlined in #119 for vim-prettier, which is currently linked as part of the documentation. I also found it weird to have both vim-prettier and coc-prettier installed as a vim plugin.
However, when I was documenting it all down, by a struck of chance I have found a gem in #263. As far as I can tell, the solution requires just a few steps. Install plugin-php as a project dependency:
npm install -D @prettier/plugin-php
Then edit your vimrc
file:
call plug#begin('~/.vim/plugged')
Plug 'prettier/vim-prettier', { 'do': 'npm install', 'for': ['php'] }
call plug#end()
autocmd BufWritePre *.php PrettierAsync
Run :PlugInstall
and you are ready to go. As we can see, the
vim-prettier
is only enabled for PHP files, as others are handled by
coc-prettier
in my setup. Seeing these two actually work together side-by
side without issues made me more comfortable with this setup and my
reluctance diminished.
What I really like about this setup is it's simplicity and also the fact it
respects the project-wide .prettierrc
file, exactly according to my
taste, for example:
{
"tabWidth": 4,
"semi": false,
"singleQuote": true,
"trailingComma": "es5",
"trailingCommaPHP": true,
"proseWrap": "always",
"arrowParens": "avoid",
"bracketSpacing": true,
"phpVersion": "8.0",
"braceStyle": "1tbs"
}
Both standard prettier options as well as ones from
plugin-php configuration
neatly in one place. The disadvantage is that if you want different
tabWidth
for different file types across project, it could not be done
exactly this way. But then, this would go slightly against the prettier's
philosophy being opinionated and consistent.
I wish I've found this solution right at the beginning, but hey, better later than never. Happy writing!