使用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自动适应范围的分页代码
Aug 05 PHP
php mysql Errcode: 28 终极解决方法
Jul 01 PHP
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
Apr 25 PHP
php树型类实例
Dec 05 PHP
php简单实现短网址(短链)还原的方法(测试可用)
May 09 PHP
ThinkPHP打水印及设置水印位置的方法
Oct 14 PHP
php 静态属性和静态方法区别详解
Apr 09 PHP
thinkphp实现附件上传功能
May 26 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
Sep 21 PHP
浅谈php使用curl模拟多线程发送请求
Mar 08 PHP
Yii 使用intervention/image拓展实现图像处理功能
Jun 22 PHP
php实现简易计算器
Aug 28 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 substr,mb_substr以及mb_strcut的区别和用法
2013/06/21 PHP
PHP数字和字符串ID互转函数(类似优酷ID)
2014/06/30 PHP
MyEclipse常用配置图文教程
2014/09/11 PHP
浅谈本地WAMP环境的搭建
2015/05/13 PHP
PHP简单的MVC框架实现方法
2015/12/01 PHP
PHP操作FTP类 (上传、下载、移动、创建等)
2016/03/31 PHP
top.location.href 没有权限 解决方法
2008/08/05 Javascript
IE bug table元素的innerHTML
2010/01/11 Javascript
JavaScript DOM学习第四章 getElementByTagNames
2010/02/19 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
JQquery的一些使用心得分享
2012/08/01 Javascript
jQuery 1.8 Release版本发布了
2012/08/14 Javascript
IE下通过a实现location.href 获取referer的值
2014/09/04 Javascript
DOM基础教程之事件类型
2015/01/20 Javascript
推荐10 款 SVG 动画的 JavaScript 库
2015/03/24 Javascript
jQuery实现仿QQ头像闪烁效果的文字闪动提示代码
2015/11/03 Javascript
AngularJS Bootstrap详细介绍及实例代码
2016/07/28 Javascript
js仿腾讯QQ的web登陆界面
2016/08/19 Javascript
原生ajax处理json格式数据的实例代码
2016/12/25 Javascript
原生js仿浏览器滚动条效果
2017/03/02 Javascript
详解Vue CLI3配置解析之css.extract
2018/09/14 Javascript
使用js在layui中实现上传图片压缩
2019/06/18 Javascript
Vue实现购物车实例代码两则
2020/05/30 Javascript
javascript实现一款好看的秒表计时器
2020/09/05 Javascript
jQuery冲突问题解决方法
2021/01/19 jQuery
[01:42]DOTA2 – 虚无之灵
2019/08/25 DOTA
浅谈python对象数据的读写权限
2016/09/12 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
python3.7简单的爬虫实例详解
2019/07/08 Python
pygame实现俄罗斯方块游戏(基础篇3)
2019/10/29 Python
Hunkemöller西班牙:欧洲最大的内衣连锁店
2018/08/15 全球购物
Linux内核的同步机制是什么?主要有哪几种内核锁
2013/01/03 面试题
酒店管理失职检讨书
2014/09/16 职场文书
婚前协议书范本
2014/10/27 职场文书
诺贝尔奖获得者名言100句:句句启人心智,值永久收藏
2019/08/09 职场文书
「女孩的钓鱼慢活」全新版权绘公布
2022/03/21 日漫