先日、「自動生成で楽するPHPのDB処理」という記事を書きましたが、MyGenerationというツールに依存したものでした。
今回は、PHPに生成させてしまいます。
GenerateModelクラス
やっていることは、MyGeneration版と全く同じです。
前の記事にあるCapsuleライブラリが必須なのであらかじめダウンロードしておいてください。
その後、以下のクラスをCapsuleディレクトリに配置してください。
<?php /** * モデルクラスの自動生成 * @author Daijiro Abe * @date 2007.12.06 */ require_once("adodb/adodb.inc.php"); class GenerateModels { var $dsn; var $dir = "classes"; var $sep = "/"; function GenerateModels($dsn) { $this->dsn = $dsn; } /** * 生成ディレクトリを返します * @return 生成ディレクトリ名 */ function getDirectory() { $dir = $this->dir; if(substr($dir, strlen($dir)-1, 1) != $this->sep) $dir .= $this->sep; return $dir; } /** * 生成ディレクトリを設定します * @param $dir 生成ディレクトリ */ function setDirectory($dir) { $this->dir = $dir; } /** * ディレクトリセパレータを返します * @return ディレクトリセパレータ */ function getSeparator() { return $this->sep; } /** * ディレクトリセパレータを設定します * @param $sep ディレクトリセパレータ */ function setSeparator($sep) { $this->sep = $sep; } /** * クラスファイルの生成 * @return 失敗時にfalse、それ以外でtrue */ function generate() { $conn = &ADONewConnection($this->dsn); $date = date("Y/m/d"); $dsn = $this->dsn; $fp = fopen($this->dir . $this->sep . "CommonDAO.php", "w"); if(!$fp) return false; $body = <<< PHP_END <?php /** * @class CommonDAO * @brief 共通DAOクラス * @author Daijiro Abe * @date {$date} */ require_once(dirname(__FILE__) . '/../lib/Capsule/AbstractDAO.php'); require_once(dirname(__FILE__) . '/../lib/Capsule/AbstractDTO.php'); require_once(dirname(__FILE__) . '/../lib/Capsule/Collection.php'); class CommonDAO extends AbstractDAO { function CommonDAO() { \$this->connect("{$dsn}"); } } PHP_END; if(fwrite($fp, $body) === FALSE) return false; fclose($fp); $tables = $conn->MetaTables("TABLES"); foreach($tables as $table) { $columns = $conn->MetaColumnNames($table, true); $pkeys = $conn->MetaPrimaryKeys($table); $class_name = ucfirst($table); $dirpath = $this->dir . $this->sep . $class_name; if(!file_exists($dirpath)) mkdir($dirpath); $dirpath .= $this->sep; // DTOクラスの生成 $dto_class = $class_name; $dto_path = $dirpath . $dto_class . ".php"; $fp = fopen($dto_path, "w"); if(!$fp) return false; $body = <<< PHP_END <?php /** * {$dto_class}クラス * @author Daijiro Abe * @date {$date} */ class {$dto_class} extends AbstractDTO { PHP_END; foreach($columns as $column) { $column = strtolower($column); $method = ucfirst($column); $body .= "\tfunction get$method()\n"; $body .= "\t{\n"; $body .= "\t\treturn \$this->get(\"$column\");\n"; $body .= "\t}\n"; $body .= "\tfunction set$method(\$$column)\n"; $body .= "\t{\n"; $body .= "\t\t\$this->set(\"$column\", \$$column);\n"; $body .= "\t}\n"; } $body .= "}\n"; if(fwrite($fp, $body) === FALSE) return false; fclose($fp); // Collectionクラスの生成 $collection_class = $class_name . "Collection"; $collection_path = $dirpath . $collection_class . ".php"; $fp = fopen($collection_path, "w"); if(!$fp) return false; $body = <<< PHP_END <?php /** * {$collection_class}クラス * @author Daijiro Abe * @date {$date} */ require_once(dirname(__FILE__) . "/{$class_name}.php"); class {$collection_class} extends Collection { function &makeObject(\$array) { \$obj = new {$class_name}(\$array); return \$obj; } } PHP_END; if(fwrite($fp, $body) === FALSE) return false; fclose($fp); // DAOクラスの生成 $dao_class = $class_name . "DAO"; $dao_path = $dirpath . $dao_class . ".php"; $fp = fopen($dao_path, "w"); if(!$fp) return false; $body = <<< PHP_END <?php /** * {$dao_class}クラス * @author Daijiro Abe * @date {$date} */ require_once(dirname(__FILE__) . "/../CommonDAO.php"); require_once(dirname(__FILE__) . "/{$class_name}Collection.php"); class {$dao_class} extends CommonDAO { PHP_END; if($pkeys) { $body .= "\tfunction &findByPrimaryKey("; foreach($pkeys as $index => $pkey) { $pkey = strtolower($pkey); if($index > 0) $body .= ", "; $body .= "$" . $pkey; } $body .= ")\n"; $body .= "\t{\n"; $body .= "\t\treturn \$this->queryOne(\"select * from $table where "; foreach($pkeys as $index => $pkey) { $pkey = strtolower($pkey); if($index > 0) $body .= " AND "; $body .= "$pkey = ?"; } $body .= "\", array("; foreach($pkeys as $index => $pkey) { $pkey = strtolower($pkey); if($index > 0) $body .= ", "; $body .= "$" . $pkey; } $body .= "));\n"; $body .= "\t}\n"; } $body .= "\tfunction &findAll()\n"; $body .= "\t{\n"; $body .= "\t\treturn \$this->query(\"select * from $table\");\n"; $body .= "\t}\n"; $body .= "\tfunction insert(\$".$table.")\n"; $body .= "\t{\n"; $body .= "\t\treturn \$this->doInsert(\"$table\", \$".$table."->get());\n"; $body .= "\t}\n"; if($pkeys) { $body .= "\tfunction update(\$$table)\n"; $body .= "\t{\n"; foreach($pkeys as $index => $pkey) { $pkey = strtolower($pkey); $body .= "\t\t\$" . $pkey . " = \$this->qstr(\$" . $table . "->get(\"$pkey\"));\n"; } $body .= "\t\treturn \$this->doUpdate(\"$table\", \$".$table."->get(), \""; foreach($pkeys as $index => $pkey) { $pkey = strtolower($pkey); if($index > 0) $body .= " AND "; $body .= "$pkey = \$".$pkey; } $body .= "\");\n"; $body .= "\t}\n"; } $body .= "\tfunction &createCollection(\$result)\n"; $body .= "\t{\n"; $body .= "\t\t\$collection = new " . $collection_class . "(\$result);\n"; $body .= "\t\treturn \$collection;\n"; $body .= "\t}\n"; $body .= "}\n"; if(fwrite($fp, $body) === FALSE) return false; fclose($fp); } return true; } }
このクラスが、クラス生成を行います。
実際に実行させるコードは以下のような単純なものです。
<?php require_once("lib/Capsule/GenerateModels.php"); require_once("define.php"); $generator = new GenerateModels(DATABASE_DSN); if(!$generator->generate()) print "ERROR!\n"; else print "SUCCESS!\n";
デフォルトで(上記サンプルのままで)、実行ディレクトリ下のclasses内にクラス群を生成します。
setDirectory()メソッドで変更が可能です。一応、setSeparator()メソッドでディレクトリの区切り文字を変更できますが、もしかしたらあんまり意味がないかも...。
追記
上記最後のソースで、define.phpをincludeしてますが、これはDATABASE_DSNという名前でデータベース接続のDSNをdefineしているだけです。
<?php /** * 共通定義ファイル */ define("DATABASE_DSN", "postgres://postgres:postgres@localhost/topics");
こんな感じです。