rhacoとか触ってみた 既存DBからproject.xmlのdatabaseセクションを作成するバッチ
こんな記事をみて
「やめだやめだ!Ethnaでいくぞ! - 肉とご飯と甘いもの @ sotarok」
私は、ここ数日でひとつの決心をした。
Cakeだのsymfonyだの、そんなもんはやめだ、やめ!
そういえば、もうひとつきっかけがありました。
「デザイナーでも作れるスマートWebアプリ その2 - maru.cc@はてな」このエントリのリンク元にrhaco-jaのlingrのURLがあって入ってみたってのがあった。(追記)
というわけで、調べて触ってみた。
「rhaco-ja」
「rhaco | Free Development software downloads at SourceForge.net」
sourceforge.netから、リリース版を落としてきて、チュートリアル通りにとりあえず設定して、DB操作画面とか。
リリース版(1.4.0)という書き方をした理由は、SVNのtrunk版(1.4.9)がメジャーバージョンアップじゃね?というぐらい違うからですw
リリース版の「簡易DB管理画面」というのがテーブル単位の修正や、依存関係の定義など、xmlに書く必要はありますが、書きさえすれば、結構ちゃんと出来ていて、これは期待できるかも。
で、サンプルのテーブル2つだと、実際にどんな感じかわからなかったので、ちょうど今開発を行っている案件のテーブルのxml定義を起こして動かしてみようと思いました。
で、作成したのがmake_rhaco_databasexml.php
これを使って、作成したdatabase定義を作成して、setup.phpで「生成する」ボタンを押してみたら、タイムアウトに。
setup.phpの先頭に以下を追加して再実行。
set_time_limit(0);
で、テーブル関連のクラスを作成して実行したところ、エラーに。。。
追うのもめんどくさいなぁと思ってたら、trunk版と大きく違うというのを教えてもらいました。
で、trunk版を落としてきて実行。
trunk版はデザインや各ツールも大きく変わっていました。
同じようにdatabase定義をproject.xmlにコピペして、setup.phpで「setting」を実行。
今度は動きました。
library/modelとlibrary/model/tableの下にそれぞれ174個のクラスファイルがわらわら作成されていました。
簡易DB管理画面の方も大きく変わっていていました。
触ってみた感触は、ちょっと予想と違う感じ。
質問してみたところ
maru_cc
この setup.php/database/admin って どんな位置づけなのでしょうか?
DBデータをいじるphpMySQLAdminっぽい使い方なのか
tokushima
位置づけというと? 管理者による簡易DB管理画面 というような?
maru_cc
それとも これをベースにクライアントにも見せる管理画面の元っぽいイメージなのか
tokushima
クライアントに見せるイメージではないですね
maru_cc
なるほどです
tokushima
管理者が、ちょっとデータいじりたいときに使うもの です
とのことでしたので、phpMySQLAdminのプロジェクトに特化した簡易機能という感じでした。
確かに名前も「簡易DB管理画面」ですもんね。
勝手に、実運用時の管理画面の雛形みたいなイメージを持ってしまっていました。
作りこみが必要なところは別途作るとして、設定値変更画面とかはこれをそのまま使えるみたいな。
でも、用途が違うのであれば納得な感じ。
riaf
汎用的な管理画面キットみたいなのを用意したらいいんですね。。。!
tokushima
そっすねw そしてたら、installにいれてみますか
とのことですので、今後に期待です〜
実行方法
まずは、実行方法ですが、シェル上で以下のように叩いています。
需要があって、自分も使いたくなったらWebから使えるようにしようと思ったのですが、とりあえずテストなのでこれで十分。
php make_rhaco_databasexml.php > test.xml
make_rhaco_databasexml.phpの中身
mysql_field_flagsとかを使うと取れる情報が限られているので、show create tableとかの結果をパースとかすれば、もっと詳細なものが作れるかもなーと思ったのですが、MySQLのバージョンに依存しまくるので、とりあえず無視。
あと、作成されるxmlの内容が少し古いようです。 admin="true" とかもう無いとのことでしたが、とりあえずそのまま。
<?php /** * Make Database Section for racho project.xml * * author maru_cc */ $opt = array( 'dbtype'=>'mysql', 'server'=>'HOSTNAME', 'database'=>'DBNAME', 'username'=>'USERNAME', 'password'=>'PASSWORD', ); $dbinfo = dbinfo::getInstance($opt); if (!$dbinfo) exit('error'); echo $dbinfo->makeXml(); class dbinfo { var $_opt; var $_db; function &getInstance($opt) { $classname = 'dbinfo_' . $opt['dbtype']; if (!class_exists($classname)) return false; $dbinfo =& new $classname($opt); return $dbinfo; } function dbinfo($opt) { $this->_opt = $opt; return $this->_dbconnect(); } function _dbconnect() { trigger_error('this method must overried!', E_USER_ERROR); } function makeXml() { $infolist = $this->_getinfolist(); if (!is_array($infolist) || !count($infolist)) return false; $xmltables = ''; foreach ($infolist as $tablename=>$columns) { $xmlcols = ''; if (is_array($columns)) { foreach ($columns as $col) { $xmlcols.= " <column name=\"" . $col['name'] . "\""; $xmlcols.= " type=\"" . $col['type'] . "\""; if (strlen($col['default'])) $xmlcols.= " default=\"\""; $xmlcols.= " size=\"" . $col['size'] . "\""; if ($col['require']) $xmlcols.= " require=\"true\""; //true|false if ($col['primary']) $xmlcols.= " primary=\"true\""; //true|false if (strlen($col['reference'])) $xmlcols.= " reference=\"\""; if ($col['index']) $xmlcols.= " index=\"true\""; //true|false if ($col['unique']) $xmlcols.= " unique=\"true\""; //true|false if (strlen($col['uniquewith'])) $xmlcols.= " uniquewith=\"" . $col['uniquewith'] . "\""; $xmlcols.= " />\n"; } } $xmltables.= " <table name=\"{$tablename}\" admin=\"true\">\n"; $xmltables.= $xmlcols; $xmltables.= " </table>\n"; } $xml = "<database name=\"" . $this->_opt['database'] . "\">\n"; $xml.= $xmltables; $xml.= "</database>\n"; return $xml; } function _getinfolist() { trigger_error('this method must overried!', E_USER_ERROR); } } class dbinfo_mysql extends dbinfo { function _dbconnect() { $db = mysql_connect($this->_opt['server'], $this->_opt['username'], $this->_opt['password']); if (!$db) return false; if (!mysql_select_db($this->_opt['database'], $db)) return false; $this->_db = $db; return true; } function _getinfolist() { $columntypes = array('datetime'=>'timestamp','real'=>'float','blob'=>'text'); if (!$this->_db) return false; $tables = array(); $tablesres = mysql_query("show tables", $this->_db); if (!$tablesres) return false; while ($tablerow = mysql_fetch_array($tablesres)) { $tablename = $tablerow[0]; $res = mysql_query("select * from {$tablename}", $this->_db); if (!$res) return false; $columncount = mysql_num_fields($res); $columns = array(); for ($i=0; $i < $columncount; $i++) { $type = mysql_field_type($res, $i); if (isset($columntypes[$type])) $type = $columntypes[$type]; $len = mysql_field_len($res, $i); $flags = mysql_field_flags($res, $i); $require = (strpos($flags, 'not_null')!==false); $primary = (strpos($flags, 'primary_key')!==false); if (strpos($flags, 'auto_increment')!==false) $type = 'serial'; $columns[$i] = array( 'name'=>strval(mysql_field_name($res, $i)), 'type'=>$type, 'default'=>'',///TODO 'size'=>$len, 'require'=>$require, 'primary'=>$primary, 'reference'=>'', ///TODO 'index'=>false,///TODO 'unique'=>false,///TODO 'uniquewith'=>'',///TODO 'flags'=>$flags, ); } $tables[$tablerow[0]] = $columns; } return $tables; } }
setup.phpに食わせてエラーになったら、$columntypes = array('datetime'=>'timestamp','real'=>'float','blob'=>'text'); の定義の部分の対応表を増やしてくださいませ。
自分の環境で動くことしか考えていません。。。
参考にした情報
「project.xml - nazolabo」
「No Application Configured」
「No Application Configured」
http://media.rhaco.org/project.xsd
追記
$type = 'serial'の部分修正
if ($primary) $type = 'serial';
if (strpos($flags, 'auto_increment')!==false) $type = 'serial';
なんで、イージーミスって書き込み前に気づかないかなぁ…