読者です 読者をやめる 読者になる 読者になる

VimScriptでPHPのソースコードをパースした

vim cakephp

cake.vimでModelのテーブル構造を確認する - yuhei.kagayaの課題、
Modelのファイルとdatabase.phpをパースして自動でDBに接続する、をやってみました。

autoload/cake.vim(github)の924行目あたりからがそれです。

対象のモデルに、$useDbConfigが設定されているかどうかを見に行く

ファイルをgrepして$useDbCondfigの行を探しました。
もしあったら、つぎのdatabase.phpのパースの時にその名前の接続設定を探しに行きます。なければ"default"です。

" useDbConfig
let cmd = 'grep -E ''^\s*var\s*\$useDbConfig\s*='' ' . self.name_to_path_model(target)
let line = system(cmd)
let db_config = matchstr(line, '\(var\s\+\$useDbConfig\s*=\s*["'']\)\zs\w\+\ze\(["''];\)')
if  db_config == '' 
  let db_config = 'default'
endif

database.phpから接続設定を取ってきてDB接続

VimScript側で、database.phpの接続設定をVimの辞書の変数にするようなPHPのコードを作り、コマンドラインに渡しました。
受け取った結果をVim側で評価して変数に格納しました。

let php_code = 
      \ 'require_once("' . config_path . '");' . 
      \ '$ref = new ReflectionClass("DATABASE_CONFIG");
      \ $DatabaseConfig = $ref->newInstance();
      \ $config = "' . db_config . '";
      \ $con = $DatabaseConfig->$config;
      \ $user = $con["login"];
      \ $password = $con["password"];
      \ $host = $con["host"];
      \ $dbname = $con["database"];
      \ echo sprintf("{\"user\":\"%s\", \"password\":\"%s\", \"host\":\"%s\", \"dbname\":\"%s\"}", $con["login"], $con["password"], $con["host"], $con["database"]);'

let cmd = 'php -r ''' . php_code . ''''
let params = system(cmd)
let p = eval(params)

let options = 'type=' . g:cakephp_db_type . ':user=' . p.user . ':passwd=' . p.password . ':dbname=' . p.dbname . ':host=' . p.host .-
':port=' . g:cakephp_db_port . ':buffer_lines=' . g:cakephp_db_buffer_lines
call dbext#DB_setMultipleOptions(options)

対象のモデルに$useTableが設定されているかどうかを見に行く

$useDbConfigのときと同じように、grepとmatchstr()で設定行を取得しました。
もし$useTableが設定されていたらそのテーブル名で、設定されていなかったらModel名からテーブル名を作っています。

" useTable
let cmd = 'grep -E ''^\s*var\s*\$useTable\s*='' ' . self.name_to_path_model(target)
let line = system(cmd)
let table = matchstr(line, '\(var\s\+\$useTable\s*=\s*["'']\)\zs\w\+\ze\(["''];\)')
if table == ''
  let table = cake#util#pluralize(cake#util#decamelize(target))
endif

call dbext#DB_describeTable(table)


今回、database.phpが単純なクラスで何もrequireしていなかったので(何もrequireしないよねと願って)、PHPのReflectionでパースして接続設定を抜き出すことができました。
でも、結構強引でメンテしずらいなぁと思うので、良い方法があったら直したいです。