ER図から,Webアプリを自動生成しよう (A5SQL Mk2 + CakePHPを連携させる)
下記の流れは,一度は体験しておきたい。
- ER図を書く。
- → 1 から,DDL文+テーブルを自動生成。
- → 2 から,テーブル定義書を自動生成。
- → 2 から,Webアプリを自動生成。
コーディングなし。
例として,複数人で利用できるブックマークアプリのようなものを生成してみる。
「CakePHPが作ってくれる雛型(scaffold)はリッチだ」とよく言われるが,それを更にテーブル生成ツールと組み合わせたらどうなるか,というのが焦点。
CakePHPの入門方法もちょっと兼ねる。
事前準備(1/2):ツール
ER図描画+DDL生成+テーブル定義書生成のために,A5SQLというフリーソフトを使うのでインストールしておく。
また,DB+DB管理+PHP実行のために,XAMPP+CakePHPを使う。
XAMPPはインストールしておく。
Cakeは,下記であとでインストールする。
事前準備(2/2):DB作成
テーブルはあとで自動生成する。
だが,データベース/スキーマは先に準備しておく。
以下はMySQL/PHPMyAdminの例。
>新規データベースを作成する >データベース名 boo >照合順序 utf8_bin
で実行。
データベース boo を作成しました
実行した SQL:
CREATE DATABASE `boo` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
となる。
注:
MySQLの照合順序:utf8_unicode_ciってなんぞ?
http://cial.seesaa.net/article/704525...
http://localhost/phpmyadmin/
に戻り,
特権>新しいユーザを追加する> ユーザ名:boo_user ホスト:ローカル,localhost パスワード:boo_pass グローバル特権:すべてチェックする
で実行。
新しいユーザを追加しました
実行した SQL:
CREATE USER 'boo_user'@'localhost' IDENTIFIED BY '********';GRANT ALL PRIVILEGES ON * . * TO 'boo_user'@'localhost' IDENTIFIED BY '********' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
そして,このDBへODBC接続できるようにしておく。
下記のドライバをインストール。
MySQL Connector/ODBC 5.1 Downloads
http://dev.mysql.com/downloads/connec...
そしてWindows側で設定:
コンパネ>管理ツール>ODBC>システムDSN>追加 DSNAME:boo Server:localhost User:boo_user Pass:boo_pass DB:boo Test>Connection Successful
A5SQLを開いてみて,
左ペイン右クリック>DBの追加と削除>ODBCを列挙する
にチェックが入った状態で閉じると,上で作った「boo」が表示される。
ここまでが事前準備。
本番(1) ER図作成
下記URLに書き方・使い方が載っている。
A5:SQL Mk-2を使ってER図を描こう!!
http://www.wind.sannet.ne.jp/m_matsu/...
新規>新規ER図>プロジェクト名を入力(ここではbooという名前にする。)
図内に
- エンティティ(テーブルそのものの定義)
- リレーション(外部結合)
などを書き込んでいく。
この際に,CakePHPの流儀に合わせた入力を行なう。
ER図:エンティティの作成
ER図エディタ上で,ピンクの四角の隣のアイコン「新規エンティティ」をクリック。
エンティティ: ・論理名と物理名を入力。 フィールド: ・横移動はTABキー ・型(ドメイン)はALT+下キーで出せる ※ただしVARCHARは,選択後自分で(10)とか文字数を付加すること。 http://dev.mysql.com/doc/refman/4.1/ja/char.html ・必須チェックはスペースキーでチェックできる 決まったら,右下の適用をクリックしてダイアログを閉じる。
このとき,注意点として
- テーブルの物理名は英語小文字複数形にする。
- 主キーは id
- 外部キーは テーブル名_id
- created, modified をDATETIMEで入れる
主キーである「id」の型は,下記のように設定する。
- 型は *ID と入力。
- IDという名前の「型ドメイン」を作る。
- ドメイン編集をクリック>ドメイン名「ID」を実際のデータ型「INT unsigned auto_increment」に設定。
- not null
- キーに1と入力(主キー)
A5SQL:型ドメインとは何か
http://www.wind.sannet.ne.jp/m_matsu/...CakePHPシステムデザイン(最新規約):2007/02
http://cakephp.jp/modules/newbb/viewt...
今回は,完成版は下記のように2テーブルになる。
論理名:ユーザ
物理名:usersフィールド:
- id / id / *ID / 必須 / 1
- ユーザ名 / user_name / @VARCHAR(20) / 必須
- パスワード / user_password / @VARCHAR(20) / 必須
- 登録 / created / @DATETIME
- 更新 / modified / @DATETIME
論理名:ブックマーク
物理名:bookmarksフィールド:
- id / id / *ID / 必須 / 1
- ユーザID / user_id / @INT / 必須
- ブックマークURL / bookmark_url / @VARCHAR(200) / 必須
- コメント / bookmark_comment / @VARCHAR(200)
- 登録 / created / @DATETIME
- 更新 / modified / @DATETIME
テーブル名の末尾のsを忘れないように。
ER図:リレーションの作成
リレーションについて:
第2回 30分間データモデリング 〜ER図を描こう!〜
http://www.atmarkit.co.jp/fdb/rensai/...
- 「主体」から「行為」に向かって1:多の関係
A1つにつきBがたくさんある,という場合,親がAで子がB。
今回は,ユーザが主体でブックマークが行為だから,親がユーザとする。
A5SQL上での操作:
テーブル間で線を引っ張る: ・エンティティボタンの隣の「リレーションを追加」をクリック ・ユーザエンティティを親としてクリック ・ブックマークを子としてクリック カーディナリティ: ・ユーザ:1 ・ブックマーク:0以上 カラム: ・ユーザのIDからブックマークのuser_idへ 適用をクリック →エンティティにFKの表示が出る。
ER図完成。
これで,ほかの物は自動生成できる。
本番(2) テーブル生成
ER図から,テーブル生成のためのSQL文(DDL)を生成。
A5SQLのメニューバー上で,
ER図>DDL作成> ・MySQL, ・Drop tableを生成しない, ・外部キー制約作成 ・DBにコメント登録する >DDL生成
というように実行。
下記のようなSQLが生成される。
-- Project Name : boo -- Date/Time : 2009/01/30 16:25:26 -- Author : PCUser -- RDBMS Type : MySQL -- Application : A5:SQL Mk-2 -- ブックマーク create table bookmarks ( id INT unsigned auto_increment not null comment 'id' , user_id INT not null comment 'ユーザID' , bookmark_url VARCHAR(200) not null comment 'ブックマークURL' , bookmark_comment VARCHAR(200) comment 'コメント' , created DATETIME comment '登録' , modified DATETIME comment '更新' , primary key (id) ) ; -- ユーザ create table users ( id INT unsigned auto_increment not null comment 'id' , user_name VARCHAR(20) not null comment 'ユーザ名' , user_password VARCHAR(20) not null comment 'パスワード' , created DATETIME comment '登録' , modified DATETIME comment '更新' , primary key (id) ) ; alter table bookmarks add foreign key (user_id) references users(id);
これを,A5SQL上で実行しよう。
・左ペインでDB(さっき作ったboo)選択,右クリック>DB開く ・SQLエディタ上の左上セレクトボックスに「boo」というDB名を表示させる。 ・SQLエディタ上部で,SQL実行位置:全て実行する をクリック。 ・黄緑色のボタンで実行。
テーブルが生成された。
本番(3) テーブル定義書を生成
テーブルそのものから,テーブル定義書(.xls)を自動生成。
・A5SQLの左ペインでDB(boo)選択,接続。 ・「default」を選択して右クリック,テーブル定義書の作成 ・対象テーブルはCtrl+クリックで複数選択できる
Excelファイルが生成される。
テーブル一覧シートつき,カラー。
※CSEでも,
右ペイン>テーブル>定義書を出力
でモノクロのシンプルなXLSができる。
本番(4) Webアプリを生成
最新版(1.2)のCakePHPをダウンロード。
CakePHP
http://cakephp.org/
解凍,
cake_1.2.1.8004のフォルダを「boo」にリネームして,XAMPP Apacheのhtdocs以下にコピー。
DB接続の設定
php.exeにPATHが通っているとして,
D:\dev\xampp\htdocs\boo\cake\console(という感じのフォルダ)にてコマンドプロンプトから
php cake.php bake -app D:\dev\xampp\htdocs\boo\
(このコマンドはバッチにしてしまうのがいいだろう。)
これで対話形式で設定できる。
下記で,キー操作の部分は青くした。
(http://php.sunvisor.net/2008/12/cake12bake.html を参考。)
> のプロンプトだけの部分は,単にEnterだけ押下することを指す。
D:\dev\xampp\htdocs\boo\cake\console>php cake.php bake -app D:\dev\xampp\htdocs\
boo\
Welcome to CakePHP v1.2.1.8004 Console
- -
App : boo
Path: D:\dev\xampp\htdocs\boo
- -
What is the full path for this app including the app directory name?
Example: D:\dev\xampp\htdocs\boo\myapp
[D:\dev\xampp\htdocs\boo\myapp] > D:\dev\xampp\htdocs\boo\
Bake Project
Skel Directory: D:\dev\xampp\htdocs\boo\cake\console\libs\templates\skel
Will be copied to: D:\dev\xampp\htdocs\boo\
- -
Look okay? (y/n/q)
[y] >
Do you want verbose output? (y/n)
[n] >
- -
Created: boo in D:\dev\xampp\htdocs\boo\
- -
Creating file D:\dev\xampp\htdocs\boo\views\pages\home.ctp
Wrote D:\dev\xampp\htdocs\boo\views\pages\home.ctp
Welcome page created
Random hash key created for 'Security.salt'
CAKE_CORE_INCLUDE_PATH set to D:\dev\xampp\htdocs\boo in webroot/index.php
CAKE_CORE_INCLUDE_PATH set to D:\dev\xampp\htdocs\boo in webroot/test.php
Remember to check these value after moving to production server
Your database configuration was not found. Take a moment to create one.
- -
Database Configuration:
- -
Name:
[default] >
Driver: (db2/firebird/mssql/mysql/mysqli/odbc/oracle/postgres/sqlite/sybase)
[mysql] >
Persistent Connection? (y/n)
[n] >
Database Host:
[localhost] >
Port?
[n] >
User:
[root] > boo_user
Password:
> boo_pass
Database Name:
[cake] > boo
Table Prefix?
[n] >
Table encoding?
[n] >
- -
The following database configuration will be created:
- -
Name: default
Driver: mysql
Persistent: false
Host: localhost
User: boo_user
Pass: ********
Database: boo
- -
Look okay? (y/n)
[y] >
Do you wish to add another database configuration?
[n] >Creating file D:\dev\xampp\htdocs\boo\config\database.php
Wrote D:\dev\xampp\htdocs\boo\config\database.phpD:\dev\xampp\htdocs\boo\cake\console>
これでDB接続の設定が終わった。
にブラウザでアクセスすると,
Your database configuration file is present.
が出る。
モデル生成
もう一度同じコマンドを実行し,モデル作成。
php cake.php bake -app D:\dev\xampp\htdocs\boo\
ユーザとブックマークの2テーブルについて,モデル(M)を生成する。
Welcome to CakePHP v1.2.1.8004 Console
- -
App : boo
Path: D:\dev\xampp\htdocs\boo
- -
Interactive Bake Shell
- -
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> m
- -
Bake Model
Path: D:\dev\xampp\htdocs\boo\models\
- -
Possible Models based on your current database:
1. Bookmark
2. User
Enter a number from the list above, type in the name of another model, or 'q' to
exit
[q] > 1
Would you like to supply validation criteria for the fields in your model? (y/n)[y] > n
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)?
(y/n)
[y] >
One moment while the associations are detected.
- -
Please confirm the following associations:
- -
Bookmark belongsTo User? (y/n)
[y] >
Would you like to define some additional model associations? (y/n)
[n] >
- -
The following Model will be created:
- -
Name: Bookmark
Associations:
Bookmark belongsTo User
- -
Look okay? (y/n)
[y] >Baking model class for Bookmark...
Creating file D:\dev\xampp\htdocs\boo\models\bookmark.php
Wrote D:\dev\xampp\htdocs\boo\models\bookmark.php
Cake test suite not installed. Do you want to bake unit test files anyway? (y/n
)
[y] >You can download the Cake test suite from http://cakeforge.org/projects/testsuit
e/Baking test fixture for Bookmark...
Creating file D:\dev\xampp\htdocs\boo\tests\fixtures\bookmark_fixture.php
Baking unit test for Bookmark...
Creating file D:\dev\xampp\htdocs\boo\tests\cases\models\bookmark.test.php
- -
Interactive Bake Shell
- -
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> m
- -
Bake Model
Path: D:\dev\xampp\htdocs\boo\models\
- -
Possible Models based on your current database:
1. Bookmark
2. User
Enter a number from the list above, type in the name of another model, or 'q' to
exit
[q] > 2
Would you like to supply validation criteria for the fields in your model? (y/n)[y] > n
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)?
(y/n)
[y] >
One moment while the associations are detected.
- -
Please confirm the following associations:
- -
User hasMany Bookmark? (y/n)
[y] >
User hasOne Bookmark? (y/n)
[y] > n
Would you like to define some additional model associations? (y/n)
[n] >
- -
The following Model will be created:
- -
Name: User
Associations:
User hasMany Bookmark
- -
Look okay? (y/n)
[y] >Baking model class for User...
Creating file D:\dev\xampp\htdocs\boo\models\user.php
Wrote D:\dev\xampp\htdocs\boo\models\user.php
Cake test suite not installed. Do you want to bake unit test files anyway? (y/n
)
[y] >You can download the Cake test suite from http://cakeforge.org/projects/testsuit
e/Baking test fixture for User...
Creating file D:\dev\xampp\htdocs\boo\tests\fixtures\user_fixture.php
Wrote D:\dev\xampp\htdocs\boo\tests\fixtures\user_fixture.phpBaking unit test for User...
Creating file D:\dev\xampp\htdocs\boo\tests\cases\models\user.test.php
Wrote D:\dev\xampp\htdocs\boo\tests\cases\models\user.test.php
- -
Interactive Bake Shell
- -
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
モデル終わり。手を動かしたのは,青い部分だけ。
コントローラを作る
こんどはC。scaffold(雛型)を利用するように設定。
Welcome to CakePHP v1.2.1.8004 Console
- -
App : boo
Path: D:\dev\xampp\htdocs\boo
- -
Interactive Bake Shell
- -
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> c
- -
Bake Controller
Path: D:\dev\xampp\htdocs\boo\controllers\
- -
Possible Controllers based on your current database:
1. Bookmarks
2. Users
Enter a number from the list above, type in the name of another controller, or '
q' to exit
[q] > 1
- -
Baking BookmarksController
- -
Would you like to build your controller interactively? (y/n)
[y] >
Would you like to use scaffolding? (y/n)
[n] > y
- -
The following controller will be created:
- -
Controller Name: Bookmarks
var $scaffold;
- -
Look okay? (y/n)
[y] >Creating file D:\dev\xampp\htdocs\boo\controllers\bookmarks_controller.php
Wrote D:\dev\xampp\htdocs\boo\controllers\bookmarks_controller.php
Cake test suite not installed. Do you want to bake unit test files anyway? (y/n
)
[y] >You can download the Cake test suite from http://cakeforge.org/projects/testsuit
e/Baking unit test for Bookmarks...
Creating file D:\dev\xampp\htdocs\boo\tests\cases\controllers\bookmarks_controll
er.test.php
- -
Interactive Bake Shell
- -
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> c
- -
Bake Controller
Path: D:\dev\xampp\htdocs\boo\controllers\
- -
Possible Controllers based on your current database:
1. Bookmarks
2. Users
Enter a number from the list above, type in the name of another controller, or '
q' to exit
[q] > 2
- -
Baking UsersController
- -
Would you like to build your controller interactively? (y/n)
[y] >
Would you like to use scaffolding? (y/n)
[n] > y
- -
The following controller will be created:
- -
Controller Name: Users
var $scaffold;
- -
Look okay? (y/n)
[y] >Creating file D:\dev\xampp\htdocs\boo\controllers\users_controller.php
Wrote D:\dev\xampp\htdocs\boo\controllers\users_controller.php
Cake test suite not installed. Do you want to bake unit test files anyway? (y/n
)
[y] >You can download the Cake test suite from http://cakeforge.org/projects/testsuit
e/Baking unit test for Users...
Creating file D:\dev\xampp\htdocs\boo\tests\cases\controllers\users_controller.t
est.php
- -
Interactive Bake Shell
- -
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
コントローラ終わり。
コーディング0でWebアプリができた。
完成
で,ユーザの一覧/追加/削除/編集
で,ブックマークの一覧/追加/削除/編集
ができる。
すごい所は,
- ブックマーク追加時には,どのユーザとして追加するのかユーザIDを選択できる。
- ユーザ表示時には,関連情報として,そのユーザがブックマークしているブックマークを一覧できる。
という点。
つまり,「Wikiのように,複数のユーザ全員が自由な編集権限を持った掲示板アプリ」が完成したのだ。
- ブックマーク一覧画面(bookmarks/index)が掲示板そのものにあたり,
- 発言投稿時には発言ユーザを選択でき,
- 特定のユーザの発言のみ抽出する事もできる,
といった感じか。
考え方
ここで注目したいのは,
- ER図
- DDL
- DB上に実際に存在するテーブルそのもの
- テーブル定義書
はどれも同じ情報を表している(ダブっている)ということ。
同じ情報なら,どうして別々に編集するのか?
どれか1個書き直したら,ほかの3つも修正しないといけない。
それは手動でやるべきことだろうか。
ER図に限らず,最初にどれか一個作りやすい物を作ったら,それをモデル(M)として,ほかの3つはビュー(V)として生成するのが楽だろう。
その後で,DB構造が変わるたびに,適宜互いにリバース生成すればよい。
(テーブルからER図をリバース生成するようなこともA5SQLでできる。)
DB中のカラムを一覧にした仕様書,実際のテーブルを生成するためのSQLコマンド一式,テーブルの行ごとの内容を保持するためのプログラミング言語によるレコード構造,が存在すると考えて下さい。これでは同じ情報が3回繰り返されていることになります。
これがDRY原則に反しているのは明らかです。
この問題を回避するため,信頼できる情報源を選択する必要があります。…
モデルの情報を異なったビューへと変換する方法を考え出せばよいのです。
「達人プログラマー」8章,「実行可能ドキュメント」の副見出し
下記のエントリも関係:
テーブル定義書から,Javaのエンティティクラスを自動生成する VBA マクロ
http://language-and-engineering.hatenablog.jp/entry/20081229/1230563126
補足
Cakeの楽さを目で見るには,下記の動画がとても参考になる。
10分で作るCakePHPアプリ for Windows
http://p4life.jp/cake/
ところで,今回作成のアプリでは,全員がWikiのような自由な編集権限を持ってしまっているため,DB中で「ユーザのパスワード」が未使用になってしまった。
ここから先は,少しのコーディングを加えて改良していく。
その内容はまた次回。