使用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的可变变量名的使用方法分享
Feb 05 PHP
php中的strpos使用示例
Feb 27 PHP
zf框架的校验器InArray使用示例
Mar 13 PHP
Javascript与PHP验证用户输入URL地址是否正确
Oct 09 PHP
简单谈谈favicon
Jun 10 PHP
PHP访问数据库集群的方法小结
Mar 14 PHP
ThinkPHP连接Oracle数据库
Apr 22 PHP
PHP中类的继承和用法实例分析
May 24 PHP
PHP标准类(stdclass)用法示例
Sep 28 PHP
PHP编写daemon process 实例详解
Nov 13 PHP
yii框架搜索分页modle写法
Dec 19 PHP
在laravel框架中实现封装公共方法全局调用
Oct 14 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&amp;mysql(一)
2006/10/09 PHP
php 文件上传系统手记
2009/10/26 PHP
PHP用mysql数据库存储session的代码
2010/03/05 PHP
php 输出双引号&quot;与单引号'的方法
2010/05/09 PHP
PHP+FastCGI+Nginx配置PHP运行环境
2014/08/07 PHP
php文件上传你必须知道的几点
2015/10/20 PHP
Laravel5.* 打印出执行的sql语句的方法
2017/07/24 PHP
laravel中的一些简单实用功能
2018/11/03 PHP
Laravel 已登陆用户再次查看登陆页面的自动跳转设置方法
2019/09/30 PHP
jQuery 性能优化指南(2)
2009/05/21 Javascript
window.returnValue使用方法示例介绍
2014/07/03 Javascript
JavaScript中this的9种应用场景及三种复合应用场景
2015/09/12 Javascript
NodeJS实现阿里大鱼短信通知发送
2016/01/17 NodeJs
使用JQuery中的trim()方法去掉前后空格
2016/09/16 Javascript
VUE解决微信签名及SPA微信invalid signature问题(完美处理)
2019/03/29 Javascript
JS实现省市县三级下拉联动
2020/04/10 Javascript
vue3弹出层V3Popup实例详解
2021/01/04 Vue.js
学习Python selenium自动化网页抓取器
2018/01/20 Python
Flask之flask-session的具体使用
2018/07/26 Python
Python谱减法语音降噪实例
2019/12/18 Python
python数据预处理 :数据抽样解析
2020/02/24 Python
Python如何使用正则表达式爬取京东商品信息
2020/06/01 Python
CSS3的calc()做响应模式布局的实现方法
2017/09/06 HTML / CSS
利用HTML5中的Canvas绘制一张笑脸的教程
2015/05/07 HTML / CSS
英国鞋类及配饰零售商:Kurt Geiger
2017/02/04 全球购物
Ever New加拿大官网:彰显女性美
2018/10/05 全球购物
出纳员岗位责任制
2014/02/11 职场文书
爱心捐书活动总结
2014/07/05 职场文书
医院安全生产月活动总结
2014/07/05 职场文书
私人委托书格式
2014/09/10 职场文书
村党支部书记个人对照材料汇报
2014/10/26 职场文书
民主生活会汇报材料
2014/12/15 职场文书
2015年中秋节主持词
2015/07/30 职场文书
2016幼儿教师自荐信范文
2016/01/28 职场文书
linux中nohup和后台运行进程查看及终止
2021/06/24 Python
MySQL学习必备条件查询数据
2022/03/25 MySQL