使用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的开合式多级菜单程序
Oct 09 PHP
mysql 性能的检查和优化方法
Jun 21 PHP
有关php运算符的知识大全
Nov 03 PHP
PHP 伪静态技术原理以及突破原理实现介绍
Jul 12 PHP
thinkphp常见路径用法分析
Dec 02 PHP
yii实现图片上传及缩略图生成的方法
Dec 04 PHP
写一段简单的PHP建立文件夹代码
Jan 06 PHP
PHP file_get_contents函数读取远程数据超时的解决方法
May 13 PHP
利用PHP脚本在Linux下用md5函数加密字符串的方法
Jun 29 PHP
PHP串行化与反串行化实例分析
Dec 27 PHP
PHP实现向关联数组指定的Key之前插入元素的方法
Jun 06 PHP
Laravel 5.5官方推荐的Nginx配置学习教程
Oct 06 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实现的生成静态HTML速度快类库
2007/03/31 PHP
CI框架无限级分类+递归的实现代码
2016/11/01 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
JavaScript与Image加载事件(onload)、加载状态(complete)
2011/02/14 Javascript
动态添加option及createElement使用示例
2014/01/26 Javascript
jQuery修改li下的样式以及li下的img的src的值的方法
2014/11/02 Javascript
JS实现可展开折叠层的鼠标拖曳效果
2015/10/09 Javascript
javascript跨域总结之window.name实现的跨域数据传输
2015/11/01 Javascript
jQuery基于ajax()使用serialize()提交form数据的方法
2015/12/08 Javascript
jQuery实现导航滚动到指定内容效果完整实例【附demo源码下载】
2016/09/20 Javascript
H5基于iScroll实现下拉刷新和上拉加载更多
2017/07/18 Javascript
浅谈vue首屏加载优化
2018/06/28 Javascript
js实现图片推拉门效果代码实例
2019/05/18 Javascript
转换layUI的数据表格中的日期格式方法
2019/09/19 Javascript
JS使用正则表达式判断输入框失去焦点事件
2019/10/16 Javascript
原生javascript运动函数的封装示例【匀速、抛物线、多属性的运动等】
2020/02/23 Javascript
24个ES6方法解决JS实际开发问题(小结)
2020/05/31 Javascript
JavaScript forEach中return失效问题解决方案
2020/06/01 Javascript
在vue中axios设置timeout超时的操作
2020/09/04 Javascript
如何在 ant 的table中实现图片的渲染操作
2020/10/28 Javascript
Python线程中对join方法的运用的教程
2015/04/09 Python
python使用socket向客户端发送数据的方法
2015/04/29 Python
让python在hadoop上跑起来
2016/01/27 Python
python 系统调用的实例详解
2017/07/11 Python
Python面向对象class类属性及子类用法分析
2018/02/02 Python
Tensorflow 合并通道及加载子模型的方法
2018/07/26 Python
python查询文件夹下excel的sheet名代码实例
2019/04/02 Python
Python自省及反射原理实例详解
2020/07/06 Python
美国著名的品牌折扣店:Burlington
2017/06/08 全球购物
6PM官网:折扣鞋、服装及配饰
2018/08/03 全球购物
Super-Pharm波兰:药房和香水在一个地方
2020/08/18 全球购物
联谊活动策划书
2014/01/26 职场文书
会计人员岗位职责
2014/03/19 职场文书
公司财务会计主管应聘求职信
2014/09/26 职场文书
横店影视城导游词
2015/02/06 职场文书