使用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 相关文章推荐
JAVA/JSP学习系列之四
Oct 09 PHP
推荐php模板技术[转]
Jan 04 PHP
简化php模板页面中分页代码的解析
Feb 06 PHP
PHP 学习路线与时间表
Feb 21 PHP
php处理json时中文问题的解决方法
Apr 12 PHP
php中字符集转换iconv函数使用总结
Oct 11 PHP
PHP中如何使用session实现保存用户登录信息
Oct 20 PHP
Laravel5.1自定义500错误页面示例
Oct 09 PHP
laravel 5.3中自定义加密服务的方案详解
May 09 PHP
PHPMailer使用QQ邮箱实现邮件发送功能
Aug 18 PHP
PHP+Ajax实现的博客文章添加类别功能示例
Mar 29 PHP
Laravel5框架自定义错误页面配置操作示例
Apr 17 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/01/02 PHP
Javascript Math ceil()、floor()、round()三个函数的区别
2010/03/09 Javascript
jquery与js函数冲突的两种解决方法
2013/09/09 Javascript
javascript中的Base64、UTF8编码与解码详解
2015/03/18 Javascript
jquery实现简单手风琴菜单效果实例
2015/06/13 Javascript
javascript实现确定和取消提示框效果
2015/07/10 Javascript
js实现跨域的几种方法汇总(图片ping、JSONP和CORS)
2015/10/25 Javascript
Jquery uploadify上传插件使用详解
2016/01/13 Javascript
jQuery插件实现文件上传功能(支持拖拽)
2020/08/27 Javascript
AngularJs bootstrap详解及示例代码
2016/09/01 Javascript
js实现右键自定义菜单
2016/12/03 Javascript
vue2.0设置proxyTable使用axios进行跨域请求的方法
2017/10/19 Javascript
Vue官网todoMVC示例代码
2018/01/29 Javascript
详解webpack的proxyTable无效的解决方案
2018/06/15 Javascript
pageGroup.js实现分页功能
2019/07/27 Javascript
Vue-cli3生成的Vue项目加载Mxgraph方法示例
2020/05/31 Javascript
Vue使用Element实现增删改查+打包的步骤
2020/11/25 Vue.js
Python类属性与实例属性用法分析
2015/05/09 Python
python 筛选数据集中列中value长度大于20的数据集方法
2018/06/14 Python
numpy和pandas中数组的合并、拉直和重塑实例
2019/06/28 Python
Python定时任务APScheduler的实例实例详解
2019/07/22 Python
Python 如何创建一个线程池
2020/07/28 Python
python 基于pygame实现俄罗斯方块
2021/03/02 Python
英国假发网站:Hothair
2018/02/23 全球购物
优衣库台湾官网:UNIQLO台湾
2019/02/01 全球购物
英国玛莎百货新西兰:Marks & Spencer New Zealand
2019/07/21 全球购物
物流管理专业应届生求职信
2013/11/21 职场文书
应届大专毕业生自我鉴定
2014/04/08 职场文书
有关爱国演讲稿
2014/05/07 职场文书
交通安全责任书范本
2014/07/24 职场文书
2014年家长学校工作总结
2014/11/20 职场文书
暑期社会实践个人总结
2015/03/06 职场文书
离婚起诉书范文2015
2015/05/19 职场文书
保护环境建议书作文300字
2015/09/14 职场文书
Anaconda安装pytorch及配置PyCharm 2021环境
2021/06/04 Python
俄罗斯十大城市人口排名,第三首都仅排第六,第二是北方首都
2022/03/20 杂记