`
chennanfei
  • 浏览: 40930 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

根据表结构自动生成一个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();
分享到:
评论

相关推荐

    CodeMaker自动化代码生成工具 v2.0

    一个能够通过数据库结构,自动生成维护数据库信息的动态网页的代码生成器,可以帮助ASP、JSP、PHP开发人员快速的开发简单的数据库维护程序,无需任何编码,只需将数据库结构导入到CodeMaker中并做简单的设置,...

    维维Asp(php)数据库脚本自动生成器 v1.0

    能够根据用户提供的数据库表结构或自动获取Access的表结构,按用户的需求定制数据库脚本,实现数据库脚本程序的自动生成,提高了工作效率,尤其适用于程序员,为程序员提供了程序脚本比较详尽的程序框架,只要按实际...

    PHP版自动生成文章摘要

    最好数据表中单独一个字段放这个摘要,这样相应的数据库查询也优化了。牺牲一点点空间换很多时间还 是划算的。 再聊一下安全性问题,主要是内容安全性。如果客户端意图更改正常的摘要信息的话,一般都是BLOG的主 ...

    自动生成文章摘要的代码[PHP 版本]

    说明:这是PHP版的,用于在服务器端使用,如果你需要一个客户端版的,请阅读下一篇 我们在写BLOG这样的程序时经常需要显示文章前一部分的,但是又怕不恰当的截断破坏封闭标签以造成整个文档结构破坏,使用我的函数...

    猛犸代码生成器 v3.9

    猛犸代码生成器 更新日志:2016-09-18 Ver 3.9启用新网址,旧网址不再使用修正数据源界面mssql连接不能已windows验证登录的问题项目界面增加两个功能:1、删除表格,删除列,2、自动更新数据表结构(以前版本数据库...

    gsoap 2.8 (SOAP/XML 关于C/C++ 语言的自动化实现工具内附 CSharp webservice例子,及GSOAP client和server例子)

     ×gSOAP编译器可以根据用户定义的C和C++数据结构自动生成符合SOAP的实例化代码。  ×gSOAP支持WSDL 1.1, SOAP 1.1, SOAP 1.2, SOAP RPC 编码方式以及 literal/document 方式.  ×gSOAP是少数完全支持SOAP1.1 RPC...

    php OA 源码 办公自动化源码

    可以根据要求,自动生成日报表,周报表,月报表,自动发送到相关人员的OA文档中,达到报表自动到桌面的理想的应用境界。 报表中心可以设定相应的权限,权限可以设定到部门,指定人员,人员组。 1.10 系统管理部分 ...

    [php框架]非官方_Kohana_3_中文译本.zip

    如何生成一个很难被其他人检测到的 cmail地址 如何创建一个 email链接 如何创建一个css链接 如何创建一个脚本链接 如何显示一张图片 如何设置属性 如何使用文本类 Kohana text类是一个文木助于。它用来帮助处理...

    无限制语言代码生成器

    本工具仅仅提供一个“核心”,从各种数据库中获取数据库的全部表结构作为数据源,提供到一个模板引擎中。 模板的格式对代码生成的形式没有任何的影响和限制,因此生成的代码方式完全自由不受任何限制。 通过lua脚本...

    php网络开发完全手册

    15.4.8 一个完整的查看表中各列属性 15.4.8 的实例 258 15.5 常见问题与解决方案 259 15.6 小结 261 第16章 数据库中的程序逻辑 262 16.1 数据库程序逻辑与PHP程序逻辑的分体 16.1 设计原则 262 16.2 数据库中的程序...

    PHP和MySQL Web开发第4版pdf以及源码

    1.2 创建一个示例应用:Bob汽车零部件商店 1.2.1 创建订单表单 1.2.2 表单处理 1.3 在HTML中嵌入PHP 1.3.1 使用PHP标记 1.3.2 PHP语句 1.3.3 空格 1.3.4 注释 1.4 添加动态内容 1.4.1 调用函数 1.4.2 使用...

    PHP程序开发范例宝典III

    实例033 根据数据表结构自动生成数据录入页面 45 实例034 投票系统中单选按钮与复选框的应用 47 2.3 下拉列表的应用 50 实例035 在下拉菜单中显示数据表某列的字段值 50 实例036 在下拉菜单中显示数组中的...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    生成一个名为test.php3的文件,含有以下内容: (); ?&gt; 然后在你的浏览器中打开此文件。看看这个页面你就知道你的PHP安装使用的选项了。 2.3 语法 就像前面提到的一样,你可以混合编写你的PHP代码和HTML代码。因此...

    PHP和MySQL WEB开发(第4版)

    1.2 创建一个示例应用:Bob汽车零部件商店 1.2.1 创建订单表单 1.2.2 表单处理 1.3 在HTML中嵌入PHP 1.3.1 使用PHP标记 1.3.2 PHP语句 1.3.3 空格 1.3.4 注释 1.4 添加动态内容 1.4.1 调用函数 1.4.2 使用date()函数...

    Deftmigrations:Deftmigrations 被编码为与 Yii 框架一起使用以生成表结构或表数据的迁移文件,换句话说,它可以转储整个数据库

    Deftmigrations 被编码为与 Yii 框架一起使用来生成表结构或表数据的迁移文件,换句话说,它可以转储整个数据库。 这减少了 Yii 开发人员的手动工作。 您可以完全替换 Yii 默认迁移并使用此迁移。 如果您不想这样做...

    PHP和MySQL Web开发第4版

    1.2 创建一个示例应用:Bob汽车零部件商店 1.2.1 创建订单表单 1.2.2 表单处理 1.3 在HTML中嵌入PHP 1.3.1 使用PHP标记 1.3.2 PHP语句 1.3.3 空格 1.3.4 注释 1.4 添加动态内容 1.4.1 调用函数 1.4.2 使用...

    400个DreamWeaver插件

    mxp/分析站点的结构,产生XML结构的IMS Course Packaging Manifest文件,既一个站点结构说明文件 mxp/可以插入40多种的meta标记 mxp/插入Netscape浏览器支持的表示占据一定空间的spacer标记 mxp/一组关于iframe的...

    一款性能优越的PHP MVC框架EaglePHP(V1.4)

    11、自动生成数据库表操作,支持二次开发。 12、支持SESSION在Memcahe、Database、File中的无缝切换。 13、高安全性,内置Filter组件实现过滤机制,防止SQL注入及XSS跨站脚本攻击。 14、支持ORM,真正实现OOP开发...

    PHP3程序设计

    11.2 生成一个基类 169 11.3 继续进行下一步 171 11.4 巩固通用函数 172 11.5 添加head支持 173 11.6 添加body支持 175 11.7 添加title支持 179 11.8 添加注释支持 180 11.9 添加对通用标签的支持 183 11.10 添加...

Global site tag (gtag.js) - Google Analytics