日期:2014-05-17  浏览次数:20704 次

根据表结构自动生成一个PHP类

Zend framework提供了一种class和table映射起来的方式,创建一个继承Zend_Db_Table的class。查询时,zend自动将表字段做处理,生成一个对象,对象属性都是动态创建,所以是public的。这有两个大问题,一是class的属性是public,二是class的属性只有代码执行后才确定。于是乎,自己写了一个程序,根据表信息生成对应的class。

?

?

<?php
/**
 * 这个类的作用是从数据库里读出表结构,然后生成一个bean类,并将其属性与类一一映射。
 * 具体生成的内容包括:
 * 1. 私有变量
 * 2. 表字段与属性的映射关系
 * 3. 表字段的信息,用于server的验证
 */
class TableClassGenerator {
	const DEFAULT_DIR = 'classes';
	const DEFAULT_INDENT = 4;
	const DEFAULT_MIN = 2;
	private $excludedProperties;
    private $database;
    private $file;
    private $givenTables;
    private $parentClass;
    
    public function __construct($config) {
    	if (!isset($config) || empty($config) || ! is_array($config)) {
    		die('Invalid config: '. print_r($config, true));
    	}
    	
    	$this->database = $config['database'];
    	$conn = isset($config['password'])
        	? mysql_connect($config['host'], $config['user'], $config['password'])
    		: mysql_connect($config['host'], $config['user']);
    	if (! isset($conn)) {
    		die('Failed to connect.' . mysql_error());
    	}
    	
    	$this->givenTables = $config['tables'];
    	if (isset($this->givenTables)
    			&& (!is_array($this->givenTables)
    					|| empty($this->givenTables))) {
    		die("Tables($this->givenTables) in config is not an array or it is empty.");
    	}
    	
    	$this->parentClass = $config['parentClass'];
    	
    	if ($config['excludedProperties']) {
    		$this->excludedProperties = $config['excludedProperties'];
    		if (!is_array($this->excludedProperties)
    				|| empty($this->excludedProperties)) {
    			die('excludedProperties should be an array and shoudnot be empty.');
    		}
    	}
    	
    	if (! file_exists(self::DEFAULT_DIR)) {
    		mkdir(self::DEFAULT_DIR);
    	}
    }
    
    public function __destroy() {
        mysql_close();
    }
    
	public function generateClasses() {
		$allTables = $this->getTables();
		var_dump($allTables);

		$tables = $this->givenTables
			? $this->givenTables
			: $allTables;

    	if (empty($tables)) {
    		die("Empty given tables");
    	}
    	
    	foreach ($tables as $table) {
    		$index = array_search($table, $allTables);
    		if (!is_int($index)) {
    			echo "Table($table) not found in database({$this->database}).\n";
    			continue;
    		}
    		
    		$this->generateClassForTable($table);
    	}
    }
    
	private function generateClassForTable($table) {
        $class = ucfirst($this->transform($table));
        $fileName = self::DEFAULT_DIR . "/$class.php";
        if (file_exists($fileName)) {
        	echo "The file($fileName) already exists. You need delete if first.\n";
        	//return;
        }
        
        $columns = $this->getTableColumns($table);
        if (!isset($columns) || empty($columns)) {
		  	echo "The table($table) doesn't have columns.\n";
        	return;  	
        }
        
        $this->file = fopen($fileName, 'w');
        if (! isset($this->file)) {
        	die("Failed to open file: $fileName");
        }
        
        echo "Generating class for table: $table.\n";

        $this->writeToFile("<?php");
        if ($this->parentClass) {
        	$this->writeToFile("class $class extends {$this->parentClass} {");
        } else {
        	$this->writeToFile("class $class {");
        }

        $this->generateConst($table);
        $this->generateColumnPropMapping($columns);
        $this->generateValidateConfig($table, $columns);
        $this->generateProperties($columns);
        $this->generateGetters($columns);
        $this->generateSetters($columns);
        $this->writeToFile("}");
        $this->writeToFile("?>");

        fclose($this->file);
        echo "Class($class) was created in the file($fileName).\n\n";
    }
    
	private function generateColumnPropMapping($columns) {
		$this->wri