使用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 相关文章推荐
解析MySql与Java的时间类型
Jun 22 PHP
PHP截断标题且兼容utf8和gb2312编码
Sep 22 PHP
php json_encode值中大括号与花括号区别
Sep 30 PHP
PHP提交表单失败后如何保留已经填写的信息
Jun 20 PHP
PHP打开和关闭文件操作函数总结
Nov 18 PHP
PHP递归遍历指定目录的文件并统计文件数量的方法
Mar 24 PHP
PHP处理会话函数大总结
Aug 05 PHP
解读PHP中的垃圾回收机制
Aug 10 PHP
php脚本运行时的超时机制详解
Feb 17 PHP
php结合redis高并发下发帖、发微博的实现方法
Dec 15 PHP
YII中Ueditor富文本编辑器文件和图片上传的配置图文教程
Mar 15 PHP
laravel 时间格式转时间戳的例子
Oct 11 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设计模式之单例模式使用示例
2014/01/20 PHP
Session 失效的原因汇总及解决丢失办法
2015/09/30 PHP
4种PHP异步执行的常用方式
2015/12/24 PHP
Laravel 5.4.36中session没有保存成功问题的解决
2018/02/19 PHP
用dom+xhtml+css制作的一个相册效果代码打包下载
2008/01/24 Javascript
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
2009/11/12 Javascript
JavaScript高级程序设计 客户端存储学习笔记
2011/09/10 Javascript
JQUERY1.6 使用方法四 检测浏览器
2011/11/23 Javascript
node.js解决获取图片真实文件类型的问题
2014/12/20 Javascript
js获取json元素数量的方法
2015/01/27 Javascript
对象不支持indexOf属性或方法的解决方法(必看)
2017/05/28 Javascript
JavaScript闭包_动力节点Java学院整理
2017/06/27 Javascript
Angular2实现组件交互的方法分析
2017/12/19 Javascript
JS实现方形抽奖效果
2018/08/27 Javascript
vue-video-player 通过自定义按钮组件实现全屏切换效果【推荐】
2018/08/29 Javascript
小程序实现左右来回滚动字幕效果
2018/12/28 Javascript
独立部署小程序基于nodejs的服务器过程详解
2019/06/24 NodeJs
百度小程序之间的页面通信过程详解
2019/07/18 Javascript
Vue3 源码导读(推荐)
2019/10/14 Javascript
Python去除列表中重复元素的方法
2015/03/20 Python
Python实现获取操作系统版本信息方法
2015/04/08 Python
解决python读取几千万行的大表内存问题
2018/06/26 Python
Python3.5文件修改操作实例分析
2019/05/01 Python
Django自带的加密算法及加密模块详解
2019/12/03 Python
python实现删除列表中某个元素的3种方法
2020/01/15 Python
解决pycharm中opencv-python导入cv2后无法自动补全的问题(不用作任何文件上的修改)
2020/03/05 Python
Python代码注释规范代码实例解析
2020/08/14 Python
英文简历中的自我评价
2013/10/06 职场文书
升学宴主持词
2014/04/02 职场文书
企业文化理念标语
2014/06/10 职场文书
医德考评自我评价
2014/09/14 职场文书
中学综治宣传月活动总结
2015/05/07 职场文书
Python中X[:,0]和X[:,1]的用法
2021/05/10 Python
ajax请求前端跨域问题原因及解决方案
2021/10/16 Javascript
Java实战之课程信息管理系统的实现
2022/04/01 Java/Android
mysql 索引的数据结构为什么要采用B+树
2022/04/26 MySQL