DAO generator for PHP and MySQLを使ってみた No.2
前回の記事の続きです。
最後にちょっと疑問が残ってました。
各テーブル毎にクラスを自動的に生成し、クエリ結果をそのクラスとして返却する。
では、テーブルをJOINした場合には・・・??
で、やってみた。
まずは、DB周り。
- booksのauthorカラムをauthoridに変更(カラム名+型)
CREATE TABLE `books` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(50) DEFAULT NULL, `authorid` int(11) NOT NULL, `yearofpublication` int(11) DEFAULT NULL, `publisher` varchar(50) DEFAULT NULL, `price` int(11) DEFAULT NULL, PRIMARY KEY (`id`) )
- サンプルデータ
INSERT INTO `books` VALUES (1,'Annabel Lee',1,1849,'The Literature Page',256), (2,'The Ballad of Reading Gaol',1,1898,'The Literature Page',475), (4,'Winnetow',2,1956,'The truth',123), (5,'JBoss Tools 3',0,2009,'Packt',569);
- 新規にauthorテーブル(筆者)を用意
CREATE TABLE `author` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `birthday` date DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) )
- サンプルデータ
INSERT INTO `author` VALUES (1,'viva','2000-10-10',20), (2,'debit','1999-01-01',45);
この状態で、generate.phpを実行。※設定は、前回のまま。
出来たファイルは、これ。
で、BooksMySqlExtDAO.class.phpに以下のメソッドを追加。
<?php public function queryBooksAndAuthor(){ $sql = "SELECT * FROM books LEFT JOIN author ON authorid = author.id"; $sqlQuery = new SqlQuery($sql); return $this->getList($sqlQuery); }
で、こいつを呼び出した結果は・・・
<?php object(Book)#6 (6) { ["id"]=> string(1) "1" ["title"]=> string(11) "Annabel Lee" ["authorid"]=> string(1) "1" ["yearofpublication"]=> string(4) "1849" ["publisher"]=> string(19) "The Literature Page" ["price"]=> string(3) "256" } object(Book)#7 (6) { ["id"]=> string(1) "1" ["title"]=> string(26) "The Ballad of Reading Gaol" ["authorid"]=> string(1) "1" ["yearofpublication"]=> string(4) "1898" ["publisher"]=> string(19) "The Literature Page" ["price"]=> string(3) "475" } ・・・
あっやっぱり。
返って来るのは、あくまでもBookオブジェクトか。
必ずテーブルのクラスだという事を保障する代わりにSQLの自由度が落ちている。
これじゃJOINするとき、毎回アプリ側でやらないといけないの!?!?
めんどくさっ。
改造してみる。
こいつが原因の箇所。
<?php protected function readRow($row){ $book = new Book(); $book->id = $row['id']; $book->title = $row['title']; $book->authorid = $row['authorid']; $book->yearofpublication = $row['yearofpublication']; $book->publisher = $row['publisher']; $book->price = $row['price']; return $book;
おもいっきり固定じゃん。
で、改造版がこれ。
<?php protected function readRow($row){ $book = new Book(); $keys = array_keys($row); foreach ($keys as $key) { $book->$key = $row[$key]; } return $book;
配列のkey = Bookオブジェクトのプロパティって感じに。
これで、さっきと同じメソッドを呼び出してみる。
<?php object(Book)#6 (19) { ["id"]=> string(1) "1" ["title"]=> string(11) "Annabel Lee" ["authorid"]=> string(1) "1" ["yearofpublication"]=> string(4) "1849" ["publisher"]=> string(19) "The Literature Page" ["price"]=> string(3) "256" ["0"]=> string(1) "1" ["1"]=> string(11) "Annabel Lee" ["2"]=> string(1) "1" ["3"]=> string(4) "1849" ["4"]=> string(19) "The Literature Page" ["5"]=> string(3) "256" ["6"]=> string(1) "1" ["7"]=> string(4) "viva" ["name"]=> string(4) "viva" ["8"]=> string(10) "2000-10-10" ["birthday"]=> string(10) "2000-10-10" ["9"]=> string(2) "20" ["age"]=> string(2) "20" } ・・・
あれ?長くね?
これは、見たことがありますっ!
SQLの結果を取得するとこのオプションの問題。
なので、grepで探して変更。
generated/class/sql/QueryExecutor.class.php
<?php public static function execute($sqlQuery){ $transaction = Transaction::getCurrentTransaction(); if(!$transaction){ $connection = new Connection(); }else{ $connection = $transaction->getConnection(); } $query = $sqlQuery->getQuery(); $result = $connection->executeQuery($query); if(!$result){ throw new Exception(mysql_error()); } $i=0; $tab = array(); ★ while ($row = mysql_fetch_array($result, MYSQL_ASSOC)){ $tab[$i++] = $row; ・・・
これで取得した結果は。
<?php object(Book)#6 (9) { ["id"]=> string(1) "1" ["title"]=> string(11) "Annabel Lee" ["authorid"]=> string(1) "1" ["yearofpublication"]=> string(4) "1849" ["publisher"]=> string(19) "The Literature Page" ["price"]=> string(3) "256" ["name"]=> string(4) "viva" ["birthday"]=> string(10) "2000-10-10" ["age"]=> string(2) "20" }
OK。
使ってみて。
まだまだ、改良が必要な気がするが、templatesファイルがあるので、カスタム可能である。
また、開発初期の段階での導入には、コーディングミス軽減・繰返し作業の効率化などの点で優れている。既存システムには、導入が難しい(システムの解析が大変)のではないかと思う。