设为首页 收藏本站
查看: 367|回复: 0

[经验分享] 根据表结构自动生成一个PHP类

[复制链接]

尚未签到

发表于 2017-4-10 10:08:59 | 显示全部楼层 |阅读模式
  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();

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-362766-1-1.html 上篇帖子: PHP实现的某SNS手机游戏的简单外挂 下篇帖子: PHP 中使用 Smarty 之八:内建函数 section,sectionelse
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表