Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 5608

VimでPHPのオートローダー(vendor/autoload.php)を認識し補完や定義ジャンプを賢く行う

$
0
0

はじめに

個人的に最近はPythonやJavaScript(JSはみんなそうですよね)を触ってたりしますがPHPネタです。そしてVimネタです。 いや、むしろサーバーやクラウドなどのインフラをイジイジばかりか、コードのレビューをするくらい。コード書いてない。

さて、Vimにはphpcompleteというプラグインが同梱されています。

VimでPHPを書く際に補完、定義元ジャンプをするには標準ではタグファイルを作ってその情報を元に頑張るって方法がスタンダードかと思います。

タイトルにも書きましたが今回紹介するプラグインを使うとComposerの /vendor/autoload.phpを認識して賢く、高速に補完、定義元ジャンプができます。

また、その仕組をフックして Vimから見えるPHPの環境を変更することもできます。

PhpStormでいいじゃん って意見を言われてしまうので一応

はい。その通りです。PHP開発で現在最強のエディタ/IDEは PhpStorm で間違いないと思います。異論はありません。僕も持ってますよ。

また、最近は JetBrains 公式マニュアル日本語版βというものもあります。日本語マニュアル最高ですね。見やすい。

PhpStormでいいじゃん って人は PhpStorm 使いましょう。

ただ、状況によってはPhpStormがよしなにやってくれないほうが良いものもあるかもしれません。

例えばですが よしなにやってくれないから このメソッドの返り値でオブジェクトは何が返されてるのかなどPsySHなんかのREPLを使って調べたりするようなこととかやるかもしれませんしね。

まー。それでも基本はPhpStormを使いましょう。

phpcd.vim の紹介

Vimに同梱されている phpcomplete.vimをforkして作られた phpcd.vimというプラグインを紹介します。

phpcd.vimはPHPのReflection機構を使用してコンテキスト情報を取得するため、Vimに同梱されている phpcompete.vimより 賢く、高速になります。タグファイルを使わないのでタグファイルを作るなどの諸々の作業も必要ありません。

  • GitHub

  • 要件

    • PHP5.6以上
    • PCNTL拡張が有効になっていること
    • Vimの場合は JSON拡張が必要でNeoVimの場合は Msgpack拡張が必要

残念ながらドキュメントはこのリポジトリの README.mdしかありません。Vimのヘルプもありません。作者は中国の方です。ソース内に若干中国語のコメントがありました。

基本的にはデフォルトの状態で動きますが、まずは1つだけ phpcd.vimのオプションの設定を説明します。あとでこの値をどうのこうのしますよ。

" デフォルトの設定です。letg:phpcd_autoload_path='vendor/autoload.php'

あとは Vimを起動するカレントディレクトリに .phpcd.vimというファイルがあればそれを読み込みます。 .phpcd.vimに 設定を変更(上書き)したい内容を記載するといった使い方をします。

" ...省略function!s:init() " {{{letg:phpcd_root= phpcd#GetRoot()let phpcd_vim =g:phpcd_root.'/.phpcd.vim'if filereadable(phpcd_vim)
        exec 'source '.phpcd_vim
    endif" ... 省略

感の良い人、凄腕PHPerの方々、声の大きなPHPerの方々、PHPの毛深いの方々はもうこの段階で何ができるのかなんとなく想像付くかもしれませんね。

phpcd.vimのプラグインのインストール

個人的にはvim-plugを使用していますのでその流れで記載します。
その他のプラグインマネージャーの方は お使いのプラグインマネージャーに読み替えてください。

call plug#begin('~/.vim/plugged')" ... 色々省略" vim-plugの説明を軽くしておきます" " for はファイルタイプがphpならプラグインを読み込む " do はプラグインインストール、アップデート時に実行する内容 
Plug 'lvht/phpcd.vim',{'for':'php','do':'composer install'}" ... 色々省略call plug#end()

というかこれはプラグインのREADME.mdに書いてますね。プラグインマネージャーを使ってない方は泣きながら手動で入れるか、詳しい先輩に聞いてください。

https://github.com/lvht/phpcd.vim#installation--usage

monologを使って実際にみてみましょう

補完、定義元ジャンプのお話をしていますので実際に手を動かしてみましょうか。

Composerで何か入れてサンプルをと思います。

Composerといえば...そうですね。 monologですね。作者が一緒。 PHPのスタンダードなロガーです。

ということで monologのこちらのコードっぽくやってみましょうか

https://github.com/Seldaek/monolog#basic-usage

monologサンプルの下準備

# monologacmeってディレクトリにしますかmkdir monologacme
cd monologacme

# npmだと-yなのでよく間違えます。-nって。-nって。。-y空いてるよ。
composer init -n# monologのインストール
composer require monolog/monolog

# main.phpってファイルを作りますか
vim main.php

補完

はい。補完できてますね。 C-X C-Oです。

1_monolog1.png

docblock

補完候補の選択時に上部のウィンドウにdocblockも表示されてますね。便利ですね。

2_monolog2.png

定義元ジャンプ

定義元ジャンプをしました。 C-]ですね。
個人的にはウィンドウをスプリットして定義元ジャンプするのが多い派なので C-W C-]です。

3_monolog3.png

プラグインの中ではこのように 定義元ジャンプ元に戻るが設定されています。

https://github.com/lvht/phpcd.vim/blob/master/ftplugin/php_phpcd.vim#L4-L11

  • 対象にジャンプ: C-]
  • 対象を横分割でジャンプして開く: C-W C-]
  • 対象を縦分割でジャンプして開く: C-W C-\
  • ジャンプ先で元の対象に戻る C-t

個人的には更に <Leader>dにも割り当てたりしますのでそれを元にカスタマイズ例とします。 .vimrcにこのように書いたりします。

autocmd FileType php nnoremap <Leader>d:call<C-U>call phpcd#JumpToDefinition('split')<CR>

ユースケースとして。他言語(GoとかPythonとかJavaScriptとか諸々)のファイルでも <Leader>dで定義元ジャンプをするって形で統一してるので、まー。そんな使い方ですね。

Slimの例で変数アノテーションでの補完や定義元ジャンプ

今度はSlimを使って手を動かしてみましょうか。

マイクロフレームワークのslimでslim-skeletonを使った例です。

https://github.com/slimphp/Slim-Skeleton

# slimacmeってディレクトリにしますか
composer create-project slim/slim-skeleton slimacme
cd slimacme

# routes.php を例にしましょう
vim src/routes.php

これは routes.php です。

4_slim1.png

この1ファイルの状況だけでは 8行目の $appって何?って状態です。

8行目の時点での $app->getメソッド を補完したり getに定義元ジャンプしたりはできません。

しかし、16行目以降に変数アノテーションの例を書いてます。

ほら?バッチリ補完できてますね。

次は定義元ジャンプもできましたね。

5_slim2.png

LaravelでFacadeを補完したい(.phpcd.vimファイルを使います)

今度はLaravelを使って手を動かしてみましょうか。

あまりFacadeのことを書くとFacade警察がきたりと怖い思いをするかもしれませんが。。とりあえず責務を〜...以下省略。

LaravelのFacadeについては #phpgenba でおなじみの @shin1x1さんの記事を参照してください。

http://www.1x1.jp/blog/2014/03/laravel-facade-class.html

平たく説明するとLaraevlのフレームワークの中でゴニョゴニョとされないと、そんなstaticメソッド存在しないってものですね。

実行されないと存在しないので補完や定義元ジャンプをするのは不可能ですね。(通常では)

PhpStormではlaravel-ide-helperというツールを使いメタファイルを吐き出して補完や定義元ジャンプをしています。

https://github.com/barryvdh/laravel-ide-helper

同じ流れでVimからそのメタファイルを読み込んで補完や定義元ジャンプを行うといった方法をやります。

Laravelでの準備

Laravelには5.3からチュートリアルがありませんのでどういうサンプルが良いか考えるのが面倒。。

とりあえずcreate-projectで進めます。

# laravelacmeってディレクトリにしますか
composer create-project laravel/laravel laravelacme
cd laravelacme

# laravel-ide-helperのインストール
composer require --dev barryvdh/laravel-ide-helper
# laravel-ide-helperのide-helper:modelsコマンドで必要なためインストール
composer require --dev doctrine/dbal

# laravel-ide-helperのide-helper:modelsコマンドはDBが存在しないと駄目# ゆるふわにsqliteで用意touch database/database.sqlite
# .envファイルのDB_CONNECTIONをsqliteに変更sed-i-e's/^DB_CONNECTION=mysql/DB_CONNECTION=sqlite/' .env
# sqliteを使うので不要部分をコメントアウト(コメントアウトしないと怒られる)sed-i-e's/^DB_HOST=/#DB_HOST=/' .env
sed-i-e's/^DB_PORT=/#DB_PORT=/' .env
sed-i-e's/^DB_DATABASE=/#DB_DATABASE=/' .env
sed-i-e's/^DB_USERNAME=/#DB_USERNAME=/' .env
sed-i-e's/^DB_PASSWORD=/#DB_PASSWORD=/' .env

# コントローラーも作っておきましょうか。namespace下の説明で使うので。
php artisan make:controller TaskController

# migrateでテーブル作成
php artisan migrate

Fluent methodsのためにconfig/ide-helper.phpを作成する

あとで実行する ide-helper:generateのコマンドにて Fluent methods も含める場合はこちらの対応が必要です。

https://github.com/barryvdh/laravel-ide-helper#automatic-phpdocs-generation-for-laravel-fluent-methods

laravel-ide-helperのconfig設定を上書きするといった内容になります。

<?phpreturn['include_fluent'=>true,];

laravel-ide-helperのconfig設定(デフォルト値)自体はこちらになりますね。

https://github.com/barryvdh/laravel-ide-helper/blob/master/config/ide-helper.php

というか、これくらい、ide-helperのコマンドでオプション用意してよって感じもありますが。

ide-helperのコマンドを使い各種メタファイルの作成

各種FacadeとHelperとFluentのが作成されます。

# _ide-helper.phpというファイルが作成されます
php artisan ide-helper:generate -H# モデルの各種ドックコメントとか追加
php artisan ide-helper:models -W

Vim(phpcd.vim)で上記メタファイルを読み込むための準備

phpcd_autoload.php(PHPファイル)の作成

プロジェクトルートにてこのようなファイルを作成してください。
名称は今回の説明では phpcd_autoload.phpとします。

<?php// これはComposerのオートロードですrequire'./vendor/autoload.php';// これはlaravel-ide-helperを使って作成されたファイルですrequire'./_ide_helper.php';// php artisan ide-helper:modelsでファイル吐き出しをした場合はこちらも//require './_ide_helper_models.php';

.phpcd.vim(Vim script)の作成

Vim(phpcd.vim)からみえるPHPのオートローダーパスを先程作成したファイルを指定して変更する

letg:phpcd_autoload_path='phpcd_autoload.php'

さてプロジェクトルートでVimを立ち上げてみましょう

プロジェクトルートはこの例ですと laravelacme直下になります。

ファサード補完

Laravelのrouteファイルで試してみましょう。

:e routes/web.phpをファイルを開きます。

一番複雑なDBのファサードが補完できてますね。

6_lv1.png

ファサードでのメソッドチェーンも補完できてます

メソッドチェーンもバッチリですね(ある程度)

7_lv2.png

namespace下の場合

グローバルなネームスペース環境にファサードは読み込まれてますので バックスラッシュ(\)を忘れずに。

8_lv3.png

ちなみにPhpStormではバックスラッシュなしでも補完できます。

ファサードについて補足

よく使われるRouteファサードについてはこのようにフレームワーク側でドックコメントを頑張って書いてくれてます。

useすればstaticメソッドも呼び出すことが可能です。

コードを抜粋します。

<?phpnamespaceIlluminate\Support\Facades;/**
 * @method static \Illuminate\Support\Facades\Route get(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route post(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route put(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route delete(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route patch(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route options(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route any(string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route match(array|string $methods, string $uri, \Closure|array|string|null $action = null)
 * @method static \Illuminate\Support\Facades\Route prefix(string  $prefix)
 * @method static \Illuminate\Routing\PendingResourceRegistration resource(string $name, string $controller, array $options = [])
 * @method static \Illuminate\Routing\PendingResourceRegistration apiResource(string $name, string $controller, array $options = [])
 * @method static \Illuminate\Support\Facades\Route middleware(array|string|null $middleware)
 * @method static \Illuminate\Support\Facades\Route substituteBindings(\Illuminate\Support\Facades\Route $route)
 * @method static void substituteImplicitBindings(\Illuminate\Support\Facades\Route $route)
 * @method static \Illuminate\Support\Facades\Route as(string $value)
 * @method static \Illuminate\Support\Facades\Route domain(string $value)
 * @method static \Illuminate\Support\Facades\Route name(string $value)
 * @method static \Illuminate\Support\Facades\Route namespace(string $value)
 * @method static \Illuminate\Support\Facades\Route where(array|string $name, string $expression = null)
 * @method static \Illuminate\Routing\Router group(\Closure|string|array $value)
 * @method static \Illuminate\Support\Facades\Route redirect(string $uri, string $destination, int $status = 301)
 * @method static \Illuminate\Support\Facades\Route view(string $uri, string $view, array $data = [])
 *
 * @see \Illuminate\Routing\Router
 */classRouteextendsFacade

今度は先程説明したDBファサードをみてみましょう。

<?phpnamespaceIlluminate\Support\Facades;/**
 * @see \Illuminate\Database\DatabaseManager
 * @see \Illuminate\Database\Connection
 */classDBextendsFacade

@seeって。 @seeって。。 @seeって。。。

Route側に書いたならせっかくなら他ファサードでも書けるものだけでも良いから書いてよっていうのが本音ですがね。

まとめ

いかがでしたでしょうか?PHPでもVimで補完や定義元ジャンプがある程度、快適になります。(ある程度)

正直、言うと諸々細かな部分はまだまだなところもあります。チェーンメソッドのチェーンメソッドのチェーンメソッドとか。それこそ小さな不具合とか。

他言語では例えば補完なら PythonならJedi, JavaScriptならtern, Goならgocode, TypeScriptならtsserverなどスタンダードな補完エンジンのツールがあったり言語自体が用意していたりします。

残念ながら今のところPHPはありません。あるなら教えてください。

現在ではLSP(language server protocol)なんてものもありますが個人的に使用した印象としてはまだまだなところも感じてます。あくまで仕様の統一をといった段階で快適か、便利かといったところのフェイズに到達するには時間がかかるでしょう。

phpcd.vimを使って気になるところはPRでもしてください。便利になったら僕がハッピーなので。

もしくは phpcd.vimは Vimとの諸々のやり取りはVim scriptですが処理などの部分はPHPで出来ています。
nikic/PHP-Parserを使って頑張ってる感じです。

この記事を読んだ凄腕PHPerの方々、声の大きなPHPerの方々、PHPの毛深い方々が よし、俺がPHPの補完エンジンを作ってやる!となるのを期待してます。

改めてですが便利になったら僕がハッピーなので。

宜しくお願いします!!

次回予告

次回はLinter(phpcs)やFormatter(phpcbfとかphp-cs-fixer)とVimで連携することやPhpStormのShift×2回相当なことをやるとか。PHPのドキュメント出したりとか。ファイル内に宣言されているクラス、変数、メソッドの一覧を出す方法とか。スニペットで今回お話した補完とは別の粒度のcompletefuncのお話(入力しながら候補をしぼっていくやつ)とか。ファイラーとか。そんな粒度で他言語もとか。

諸々をお伝えするかもしれませんが お伝えしないかもしれません(あまのじゃく)


Viewing all articles
Browse latest Browse all 5608

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>