使用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环境配置 php5 MySQL5 apache2 phpmyadmin安装与配置图文教程
Mar 16 PHP
php简单提示框alert封装函数
Aug 08 PHP
需要注意的几个PHP漏洞小结
Feb 05 PHP
处理单名多值表单的详解
Jun 08 PHP
php实现邮件发送并带有附件
Jan 24 PHP
查找php配置文件php.ini所在路径的二种方法
May 26 PHP
PHP安全的URL字符串base64编码和解码
Jun 19 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
Oct 21 PHP
为PHP5.4开启Zend OPCode缓存
Dec 26 PHP
PHP strtotime函数用法、实现原理和源码分析
Feb 04 PHP
PHP5.5.15+Apache2.4.10+MySQL5.6.20配置方法分享
May 06 PHP
thinkphp实现把数据库中的列的值存到下拉框中的方法
Jan 20 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实现把MySQL数据库导出为.sql文件实例(仿PHPMyadmin导出功能)
2014/05/10 PHP
smarty高级特性之对象的使用方法
2015/12/25 PHP
thinkphp5.1 文件引入路径问题及注意事项
2018/06/13 PHP
js函数排序的实例代码
2013/07/01 Javascript
限制textbox或textarea输入字符长度的JS代码
2013/10/16 Javascript
javascripit实现密码强度检测代码分享
2013/12/12 Javascript
js动态创建标签示例代码
2014/06/09 Javascript
jQuery实现仿百度帖吧头部固定导航效果
2015/08/07 Javascript
javascript入门教程基础篇
2015/11/16 Javascript
javascript函数命名的三种方式及区别介绍
2016/03/22 Javascript
js实现按座位号抽奖
2017/04/05 Javascript
xmlplus组件设计系列之网格(DataGrid)(10)
2017/05/05 Javascript
Bootstrap Table 在指定列中添加下拉框控件并获取所选值
2017/07/31 Javascript
原生JavaScript实现remove()和recover()功能示例
2018/07/24 Javascript
教你如何用Node实现API的转发(某音乐)
2019/09/20 Javascript
Vue中使用JsonView来展示Json树的实例代码
2020/11/16 Javascript
[56:00]DOTA2上海特级锦标赛主赛事日 - 4 胜者组决赛Secret VS Liquid第一局
2016/03/05 DOTA
使用Python将数组的元素导出到变量中(unpacking)
2016/10/27 Python
Python编程实战之Oracle数据库操作示例
2017/06/21 Python
python实现简单中文词频统计示例
2017/11/08 Python
Python二叉树的定义及常用遍历算法分析
2017/11/24 Python
python实现猜单词小游戏
2020/05/22 Python
Python设计模式之命令模式原理与用法实例分析
2019/01/11 Python
浅谈sklearn中predict与predict_proba区别
2020/06/28 Python
python报错: 'list' object has no attribute 'shape'的解决
2020/07/15 Python
关于前端上传文件全面基础扫盲贴(入门)
2019/08/01 HTML / CSS
介绍java中初始化块的使用
2012/09/11 面试题
活动志愿者自荐信
2014/01/27 职场文书
市级文明单位申报材料
2014/05/07 职场文书
建筑投标担保书
2014/05/20 职场文书
2014派出所所长群众路线对照检查材料思想汇报
2014/09/18 职场文书
个人党性分析总结
2015/03/05 职场文书
2015年国庆节慰问信
2015/03/23 职场文书
物流仓管员岗位职责
2015/04/01 职场文书
画展观后感
2015/06/17 职场文书
python本地文件服务器实例教程
2021/05/02 Python