使用PHP反射机制来构造"CREATE TABLE"的sql语句


Posted in PHP onMarch 21, 2019

反射是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。

其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。

php反射api由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互。借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传递参数,动态调用类的静态方法。

反射api是php内建的oop技术扩展,包括一些类,异常和接口,综合使用他们可用来帮助我们分析其它类,接口,方法,属性,方法和扩展。这些oop扩展被称为反射。

下面的程序使用Reflection来构造"CREATE TABLE"的sql语句。如果你不是很熟悉反射机制,可以从这个程序中看看反射的魅力与作用。

<?php
/**
 * Creates an SQL 'Create Table' based upon an entity
 * @author Chris Tankersley <chris@ctankersley.com>
 * @copyright 2010 Chris Tankersley
 * @package PhpORM_Cli
 */
class PhpORM_Cli_GenerateSql
{
  /**
   * Use a MySQL database
   */
  const MYSQL = 'mysql';
  /**
   * Use a SQLite database
   */
  const SQLITE = 'sqlite';
  /**
   * Types that are allowed to have a length
   * @var array
   */
  protected $_hasLength = array('integer', 'varchar');
  /**
   * Regexes needed to pull out the different comments
   * @var array
   */
  protected $_regexes = array(
    'type' => '/ type=([a-z_]*) /',
    'length' => '/ length=([0-9]*) /',
    'default' => '/ default="(.*)" /',
    'null' => '/ null /',
  );
  /**
   * Types that we support
   * @var array
   */
  protected $_validTypes = array(
    'boolean' => 'BOOL',
    'date' => 'DATE',
    'integer' => 'INT',
    'primary_autoincrement' => 'INT AUTO_INCREMENT PRIMARY KEY',
    'text' => 'TEXT',
    'timestamp' => 'TIMESTAMP',
    'varchar' => 'VARCHAR',
  );
  /**
   * Name of the class we will interperet
   * @var string
   */
  protected $_className;
  /**
   * Name of the table we are generating
   * @var string
   */
  protected $_tableName;
  /**
   * The type of database we are generating
   * @var string
   */
  protected $_type;
  /**
   * Sets the name of the class we are working with
   * @param string $class
   * @param string $table_name
   * @param string $type
   */
  public function __construct($class, $table_name, $type = self::MYSQL)
  {
    $this->_className = $class;
    $this->_tableName = $table_name;
    $this->_type = $type;
  }
  /**
   * Builds an SQL Line for a property
   * @param ReflectionProperty $property
   * @return string
   */
  protected function _getDefinition($property)
  {
    $type = '';
    $length = '';
    $null = '';
    preg_match($this->_regexes['type'], $property->getDocComment(), $matches);
    if(count($matches) == 2) {
      if(array_key_exists($matches[1], $this->_validTypes)) {
        $type = $this->_validTypes[$matches[1]];
        if(in_array($matches[1], $this->_hasLength)) {
          $length = $this->_getLength($property);
        }
        if($matches[1] != 'primary_autoincrement') {
          $null = $this->_getNull($property);
        }
        $sql = '`'.$property->getName().'` '.$type.' '.$length.' '.$null;
        return $sql;
      } else {
        throw new Exception('Type "'.$matches[1].'" is not a supported SQL type');
      }
    } else {
      throw new Exception('Found '.count($matches).' when checking Type for property '.$property->getName());
    }
  }
  /**
   * Extracts the Length from a property
   * @param ReflectionProperty $property
   * @return string
   */
  protected function _getLength($property)
  {
    preg_match($this->_regexes['length'], $property->getDocComment(), $matches);
    if(count($matches) == 2) {
      return '('.$matches[1].')';
    } else {
      return '';
    }
  }
  /**
   * Determines if a Property is allowed to be null
   * @param ReflectionProperty $property
   * @return string
   */
  protected function _getNull($property)
  {
    preg_match($this->_regexes['null'], $property->getDocComment(), $matches);
    if(count($matches) == 1) {
      return 'NULL';
    } else {
      return 'NOT NULL';
    }
  }
  /**
   * Generates a block of SQL to create a table from an Entity
   * @return string
   */
  public function getSql()
  {
    $class = new ReflectionClass($this->_className);
    $definitions = array();
    foreach($class->getProperties() as $property) {
      if(strpos($property->getName(), '_') === false) {
        $definitions[] = $this->_getDefinition($property);
      }
    }
    $columns = implode(",n", $definitions);
    $sql = "CREATE TABLE ".$this->_tableName." (".$columns.")";
    if($this->_type == self::MYSQL) {
      $sql .= " ENGINE=MYISAM";
    }
    return $sql.";";
  }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

PHP 相关文章推荐
使用PHP批量生成随机用户名
Jul 10 PHP
phpmyadmin 访问被拒绝的真实原因
Jun 15 PHP
PHP通过header实现文本文件下载的代码
Aug 08 PHP
php去掉字符串的最后一个字符附substr()的用法
Mar 23 PHP
几个有用的php字符串过滤,转换函数代码
May 01 PHP
PHP闭包(Closure)使用详解
May 02 PHP
PHP根据IP地址获取所在城市具体实现
Nov 27 PHP
PHP中如何实现常用邮箱的基本判断
Jan 07 PHP
CodeIgniter中实现泛域名解析
Jul 19 PHP
php is_executable判断给定文件名是否可执行实例
Sep 26 PHP
php读取和保存base64编码的图片内容
Apr 22 PHP
php实现与python进行socket通信的方法示例
Aug 30 PHP
启用OPCache提高PHP程序性能的方法
Mar 21 #PHP
Discuz不使用插件实现简单的打赏功能
Mar 21 #PHP
PHP+RabbitMQ实现消息队列的完整代码
Mar 20 #PHP
PHP实现的数据对象映射模式详解
Mar 20 #PHP
PHP单例模式数据库连接类与页面静态化实现方法
Mar 20 #PHP
PHP实现的策略模式示例
Mar 20 #PHP
PHP实现数组和对象的相互转换操作示例
Mar 20 #PHP
You might like
PHP 引用是个坏习惯
2010/03/12 PHP
php简单smarty入门程序实例
2015/06/11 PHP
PHP错误处理函数
2016/04/03 PHP
DHTML Slide Show script图片轮换
2008/03/03 Javascript
Jquery 学习笔记(一)
2009/10/13 Javascript
jQuery实现鼠标移到元素上动态提示消息框效果
2013/10/20 Javascript
JavaScript字符串对象toUpperCase方法入门实例(用于把字母转换为大写)
2014/10/17 Javascript
浅谈JavaScript function函数种类
2014/12/29 Javascript
javascript动态添加删除tabs标签的方法
2015/07/06 Javascript
JavaScript实现数组降维详解
2017/01/05 Javascript
基于JavaScript实现屏幕滚动效果
2017/01/18 Javascript
bootstrapValidator 重新启用提交按钮的方法
2017/02/20 Javascript
详解使用angular的HttpClient搭配rxjs
2017/09/01 Javascript
解决vuejs 使用value in list 循环遍历数组出现警告的问题
2018/09/26 Javascript
js中事件对象和事件委托的介绍
2019/01/21 Javascript
Vuex模块化应用实践示例
2020/02/03 Javascript
[01:03:54]Liquid vs IG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[50:22]完美盛典-2018年度红毯走秀
2018/12/16 DOTA
Django中几种重定向方法
2015/04/28 Python
Python中的自省(反射)详解
2015/06/02 Python
解析Python编程中的包结构
2015/10/25 Python
Django ImageFiled上传照片并显示的方法
2019/07/28 Python
高级护理专业大学生求职信
2013/10/24 职场文书
在职人员函授期间自我评价分享
2013/11/08 职场文书
药剂专业学生求职信范文
2013/12/28 职场文书
元旦晚会邀请函
2014/01/27 职场文书
优秀学生获奖感言
2014/02/15 职场文书
表决心的诗句大全
2014/03/11 职场文书
简历中个人自我评价分享
2014/03/15 职场文书
2015国庆节66周年演讲稿
2015/03/20 职场文书
《跨越海峡的生命桥》教学反思
2016/02/18 职场文书
靠谱的活动总结
2019/04/16 职场文书
PL350与SW11的比较
2021/04/22 无线电
vue引入Excel表格插件的方法
2021/04/28 Vue.js
如何用Node.js编写内存效率高的应用程序
2021/04/30 Javascript
经典《舰娘》游改全新动画预告 预定11月开播
2022/04/01 日漫