使用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
PHP VS ASP
Oct 09 PHP
PHP读取xml方法介绍
Jan 12 PHP
PHP 简易输出CSV表格文件的方法详解
Jun 20 PHP
phpnow php探针环境检测代码
Nov 04 PHP
Thinkphp中的curd应用实用要点
Jan 04 PHP
PHP使用反射机制实现查找类和方法的所在位置
Apr 22 PHP
PHP 闭包详解及实例代码
Sep 28 PHP
PHP链表操作简单示例
Oct 15 PHP
PHP获取input输入框中的值去数据库比较显示出来
Nov 16 PHP
PHP+MYSQL实现读写分离简单实战
Mar 13 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
Jun 21 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
phpmyadmin 常用选项设置详解版
2010/03/07 PHP
php绘图中显示不出图片的原因及解决
2014/03/05 PHP
C#静态方法与非静态方法实例分析
2014/09/22 PHP
php使用CURL伪造IP和来源实例详解
2015/01/15 PHP
smarty内置函数section的用法
2015/01/22 PHP
PHP中spl_autoload_register()函数用法实例详解
2016/07/18 PHP
Fleaphp常见函数功能与用法示例
2016/11/15 PHP
RR vs IO BO3 第一场2.13
2021/03/10 DOTA
JavaScript 学习笔记(十六) js事件
2010/02/01 Javascript
javascript数组克隆简单实现方法
2015/12/16 Javascript
Node.js中路径处理模块path详解
2016/11/14 Javascript
JavaScript ES6中export、import与export default的用法和区别
2017/03/14 Javascript
JS 插件dropload下拉刷新、上拉加载使用小结
2017/04/13 Javascript
用js实现before和after伪类的样式修改的示例代码
2017/09/07 Javascript
webpack4 CSS Tree Shaking的使用
2018/09/03 Javascript
Javascript删除数组里的某个元素
2019/02/28 Javascript
详解JS深拷贝与浅拷贝
2020/08/04 Javascript
JS闭包原理及其使用场景解析
2020/12/03 Javascript
[12:36]《DOTA2》国服注册与激活指南全攻略
2013/04/28 DOTA
Python基于pygame实现的font游戏字体(附源码)
2015/11/11 Python
深入理解NumPy简明教程---数组1
2016/12/17 Python
Python3爬虫学习之爬虫利器Beautiful Soup用法分析
2018/12/12 Python
Python with关键字,上下文管理器,@contextmanager文件操作示例
2019/10/17 Python
pygame实现俄罗斯方块游戏(基础篇1)
2019/10/29 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
全球性的在线时尚男装零售商:boohooMAN
2016/12/17 全球购物
Blancsom美国/加拿大:服装和生活用品供应商
2018/07/27 全球购物
乌克兰电子产品和家用电器购物网站:TOUCH
2019/08/09 全球购物
什么是聚集索引和非聚集索引
2012/01/17 面试题
产品开发计划书
2014/04/27 职场文书
团拜会策划方案
2014/06/07 职场文书
竞选学委演讲稿
2014/09/13 职场文书
医药公司采购员岗位职责
2015/04/03 职场文书
2021-4-5课程——SQL Server查询【3】
2021/04/05 SQL Server
如何打开Win11系统注册表编辑器?Win11注册表编辑器打开修复方法
2022/04/05 数码科技
一级电子管军用接收机测评
2022/04/05 无线电