PHPで自動生成して楽するPHPのDB処理

PHPで生成するPHP

先日、「自動生成で楽する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;
    }
}

GenerateModels.php

このクラスが、クラス生成を行います。
実際に実行させるコードは以下のような単純なものです。

<?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");

こんな感じです。

LINEで送る
Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です