使用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中数组元素升序、降序以及重新排序的函数
Jun 20 PHP
php上传文件中文文件名乱码的解决方法
Nov 01 PHP
php实现简单文件下载的方法
Jan 30 PHP
php基础教程
Aug 26 PHP
Session 失效的原因汇总及解决丢失办法
Sep 30 PHP
详解WordPress中给链接添加查询字符串的方法
Dec 18 PHP
PHP将二维数组某一个字段相同的数组合并起来的方法
Feb 26 PHP
php利用gd库为图片添加水印
Nov 09 PHP
PHP设置Cookie的HTTPONLY属性方法
Feb 09 PHP
phpStudy配置多站点多域名方法及遇到的403错误解决方法
Oct 19 PHP
php使用fullcalendar日历插件详解
Mar 06 PHP
PHP使用ajax的post方式下载excel文件简单示例
Aug 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的CMS中展示文章类实例分析
2015/06/18 PHP
php 微信开发获取用户信息如何实现
2016/12/13 PHP
Laravel框架在本地虚拟机快速安装的方法详解
2018/06/11 PHP
js删除所有的cookie的代码
2010/11/25 Javascript
使用jquery动态加载javascript以减少服务器压力
2012/10/29 Javascript
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
jquery事件重复绑定的快速解决方法
2014/01/03 Javascript
jQuery on方法传递参数示例
2014/12/09 Javascript
浅谈javascript语法和定时函数
2015/05/03 Javascript
jQuery实现的个性化返回底部与返回顶部特效代码
2015/10/30 Javascript
jQuery中的通配符选择器使用总结
2016/05/30 Javascript
利用jQuery.Validate异步验证用户名是否存在(推荐)
2016/12/09 Javascript
js实现下拉框效果(select)
2017/03/28 Javascript
AngularJS中$http的交互问题
2017/03/29 Javascript
vue动态路由配置及路由传参的方式
2018/05/23 Javascript
vue中使用codemirror的实例详解
2018/11/01 Javascript
如何在JavaScript中优雅的提取循环内数据详解
2019/03/04 Javascript
Node.js一行代码实现静态文件服务器的方法步骤
2019/05/07 Javascript
解决React在安装antd之后出现的Can't resolve './locale'问题(推荐)
2020/05/03 Javascript
[02:48]DOTA2英雄基础教程 拉席克
2013/12/12 DOTA
[01:31]完美与DOTA2历程
2014/07/31 DOTA
[01:01:35]Optic vs paiN 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python判断文件是否存在,不存在就创建一个的实例
2019/02/18 Python
创建Shapefile文件并写入数据的例子
2019/11/26 Python
开普敦通行证:Cape Town Pass
2019/07/18 全球购物
Java的for语句中break, continue和return的区别
2013/12/19 面试题
存储过程的优缺点是什么
2015/01/10 面试题
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的
2015/07/24 面试题
医学类导师推荐信范文
2013/11/19 职场文书
安全生产检讨书
2014/01/21 职场文书
梅花魂教学反思
2014/04/25 职场文书
七夕活动策划方案
2014/08/16 职场文书
老龙头导游词
2015/02/11 职场文书
小时代观后感
2015/06/10 职场文书
Nginx+SpringBoot实现负载均衡的示例
2021/03/31 Servers
奥特曼十大神器:奥特手镯在榜,第一是贝利亚的神器
2022/03/18 日漫