Home  >  Article  >  Backend Development  >  依据表结构自动生成一个PHP类

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

WBOY
WBOYOriginal
2016-06-13 13:18:14816browse

根据表结构自动生成一个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->writeToFile('private static $_colPropMapping = array(', 1);
		
		foreach ($columns as $key => $value) {
			$prop = $this->transform($key);
			$this->writeToFile("'$key' => '$prop',", 2);
		}
		
		$this->writeToFile(');', 1);
		$this->writeNewLine();
    }
    
    private function generateConst($table) {
    	$this->writeToFile("const TABLE_NAME = '$table';", 1);
    	$this->writeNewLine();
    }
    
	private function generateGetters($columns) {
        foreach ($columns as $key => $value) {
            $prop = $this->transform($key);
        	if ($this->shouldExcludeProp($prop)) {
            	continue;
            }
            
            $method = 'get' . ucfirst($prop);
            $this->writeToFile("public function $method() {", 1);
            $this->writeToFile('return $' . "this->$prop;", 2);
            $this->writeToFile("}", 1);
            $this->writeNewLine();
        }
    }
    
    private function generateProperties($columns) {
        $keys = array_keys($columns);
        foreach ($keys as $key) {
            $prop = $this->transform($key);
            if ($this->shouldExcludeProp($prop)) {
            	continue;
            }
            $this->writeToFile("private $prop;", 1);
        }
        $this->writeNewLine();
    }
    
    private function generateSetters($columns) {
        foreach ($columns as $key => $value) {
            $prop = $this->transform($key);
        	if ($this->shouldExcludeProp($prop)) {
            	continue;
            }

            $method = 'set' . ucfirst($prop);
            $this->writeToFile("public function $method ($$prop) {", 1);
            $this->writeToFile('$' . "this->$prop = $" . "$prop;", 2);
            $this->writeToFile("}", 1);
            $this->writeNewLine();
        }
    }
    
    private function generateValidateConfig($table, $columns) {
    	$this->writeToFile('private static $_validator = array(', 1);
		$this->writeToFile("'$table' => array(", 2);
		foreach ($columns as $key => $value) {
			$this->writeToFile("'$key' => array(", 3);
			foreach ($value as $k => $v) {
				if (is_string($v)) {
					$this->writeToFile("'$k' => '$v',", 4);
				} else {
					$this->writeToFile("'$k' => $v,", 4);
				}
			}
			$this->writeToFile("),", 3);
		}
		$this->writeToFile("), // $table", 2);
		$this->writeToFile(');', 1);
		$this->writeNewLine();
    }
    
    private function getMin($max, $type) {
    	if (!isset($max)) {
    		return null;
    	}
    	
    	$min = self::DEFAULT_MIN;
    	if ($type == 'date' || $min > $max) {
    		$min = $max;
    	}
    	return $min;
    }
    
    public function getTableColumns($table) {
        $fields = mysql_list_fields($this->database, $table);
        $count = mysql_num_fields($fields);
        if (! isset($fields)) {
            die("Failed to get fields" . mysql_error());
        }

        $columns = array();
        for ($i = 0; $i < $count; $i++) {
            $flags = mysql_field_flags($fields, $i);
            $isRequired = preg_match('/not_null/', $flags);

            $col = mysql_field_name($fields, $i);
            $max = mysql_field_len($fields, $i);
            $type = mysql_field_type($fields, $i);
            $min = $this->getMin($max, $type);
            
            $columns[$col] = array(
                'isRequired' => $isRequired,
                'max' => $max,
            	'min' => $min,
                'type' => $type,
            );
        }
        
        $sortedColumns = array();
        $keys = array_keys($columns);
        sort($keys);
        foreach ($keys as $key) {
            $sortedColumns[$key] = $columns[$key];
        }
        return $sortedColumns;
    }
    
    private function getTables() {
    	$sql = "SHOW TABLES FROM {$this->database}";
    	$result = mysql_query($sql);
    	$tables = array();
    	for ($i = 0; $i < mysql_num_rows($result); $i++) {
    		$tables[] = mysql_tablename($result, $i);
    	}
    	return $tables;
    }
    
    private function shouldExcludeProp($prop) {
    	if (! isset($this->excludedProperties)) {
    		return false;
    	}
    	
        $index = array_search($prop, $this->excludedProperties);
        return is_int($index);
    }
    
	private function transform($name) {
        $words = explode('_', $name);
        $newName = null;
        foreach ($words as $word) {
            if ($newName == null) {
                $newName = $word;
            } else {
                $newName .= ucfirst($word);
            }
        }
        
        return $newName;
    }
    
    private function writeNewLine() {
    	$this->writeToFile('');
    }
    
    private function writeToFile($str, $count = 0) {
        $space = null;
        $count *= self::DEFAULT_INDENT;
        while ($count) {
            if ($space == null) {
                $space = ' ';
            } else {
                $space .= ' ';
            }
            $count--;
        }
        fwrite($this->file, $space);
        fwrite($this->file, "$str\n");
    }
} // TableClassGenerator

$gen = new TableClassGenerator(array(
    'excludedProperties' => array('id', 'userId'),
    'database' => 'mydb',
    'host' => 'localhost',
    'parentClass' => 'Base',
    'password' => 'pwd',
    // 'tables' => array('user'),
    'user' => 'userId',
));
    	
$gen->generateClasses();
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn