使用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 VS ASP
Oct 09 PHP
浅析51个PHP处理字符串的函数
Aug 02 PHP
PHP封装CURL扩展类实例
Jul 28 PHP
php 反斜杠处理函数addslashes()和stripslashes()实例详解
Dec 25 PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
Mar 13 PHP
PHP实现十进制、二进制、八进制和十六进制转换相关函数用法分析
Apr 25 PHP
自制PHP框架之模型与数据库
May 07 PHP
thinkphp查询,3.X 5.0方法(亲试可行)
Jun 17 PHP
PHP中递归的实现实例详解
Nov 14 PHP
php设计模式之装饰模式应用案例详解
Jun 17 PHP
PHP实现笛卡尔积算法的实例讲解
Dec 22 PHP
php的instanceof和判断闭包Closure操作示例
Jan 26 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网页后退不再出现过期
2007/03/08 PHP
php+iframe实现隐藏无刷新上传文件
2012/02/10 PHP
js 表格隔行颜色
2009/12/02 Javascript
深入理解Javascript闭包 新手版
2010/12/28 Javascript
JS 进度条效果实现代码整理
2011/05/21 Javascript
Jquery实现弹出层分享微博插件具备动画效果
2013/04/03 Javascript
jquery图片不完全按比例自动缩小的简单代码
2013/07/29 Javascript
JS动态添加与删除select中的Option对象(示例代码)
2013/12/25 Javascript
jQuery插件ajaxFileUpload异步上传文件
2016/10/19 Javascript
老生常谈angularjs中的$state.go
2017/04/24 Javascript
详解layui弹窗父子窗口之间传参数的方法
2018/01/16 Javascript
Vue $emit $refs子父组件间方法的调用实例
2018/09/12 Javascript
JS实现返回上一页并刷新页面的方法分析
2019/07/16 Javascript
JavaScript中变量提升机制示例详解
2019/12/27 Javascript
javascript实现滚动条效果
2020/03/24 Javascript
js闭包和垃圾回收机制示例详解
2021/03/01 Javascript
python类定义的讲解
2013/11/01 Python
Python使用multiprocessing创建进程的方法
2015/06/04 Python
Python 模拟购物车的实例讲解
2017/09/11 Python
Python实现获取照片拍摄日期并重命名的方法
2017/09/30 Python
详解python字节码
2018/02/07 Python
Python返回数组/List长度的实例
2018/06/23 Python
python实现屏保程序(适用于背单词)
2019/07/30 Python
使用python-cv2实现视频的分解与合成的示例代码
2020/10/26 Python
美国婚戒购物网站:Anjays Designs
2017/06/28 全球购物
阿迪达斯法国官方网站:adidas法国
2018/03/20 全球购物
营销主管自我评价怎么写
2013/09/19 职场文书
应届生会计求职信
2013/11/11 职场文书
如何掌握自荐信格式呢
2013/11/19 职场文书
外贸业务员岗位职责
2013/11/24 职场文书
捐献物资倡议书范文
2014/05/19 职场文书
学校端午节活动方案
2014/08/23 职场文书
《猴王出世》教学反思
2016/02/23 职场文书
pandas求平均数和中位数的方法实例
2021/08/04 Python
《火纹风花雪月无双》预告“神秘雇佣兵” 紫发剑客
2022/04/13 其他游戏
mysql sql常用语句大全
2022/06/21 MySQL