使用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极大的增强功能和性能
Oct 09 PHP
MySQL授权问题总结
May 06 PHP
PHP中基本符号及使用方法
Mar 23 PHP
PHP学习之字符串比较和查找
Apr 17 PHP
数据库中排序的对比及使用条件详解
Feb 23 PHP
smarty模板引擎之内建函数用法
Mar 30 PHP
详解PHP的Yii框架中扩展的安装与使用
Apr 01 PHP
windows server 2008/2012安装php iis7 mysql环境搭建教程
Jun 30 PHP
PHP-X系列教程之内置函数的使用示例
Oct 16 PHP
实现PHP中session存储及删除变量
Oct 15 PHP
Laravel基础_关于view共享数据的示例讲解
Oct 14 PHP
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
Apr 11 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将fileterms函数返回的结果变成可读的形式
2011/04/21 PHP
PHP中strpos、strstr和stripos、stristr函数分析
2016/06/11 PHP
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
2016/07/02 PHP
PHP实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
JavaScript 参数中的数组展开 [译]
2012/09/21 Javascript
jquery实现网站超链接和图片提示效果
2013/03/21 Javascript
常用js字符串判断方法整理
2013/10/18 Javascript
jquery教程限制文本框只能输入数字和小数点示例分享
2014/01/13 Javascript
jquery form 加载数据示例
2014/04/21 Javascript
avascript中的自执行匿名函数应用示例
2014/09/15 Javascript
javascript搜索框效果实现方法
2015/05/14 Javascript
JavaScript中定义类的方式详解
2016/01/07 Javascript
BootStrap glyphicon图标无法显示的解决方法
2016/09/06 Javascript
详解用webpack2.0构建vue2.0超详细精简版
2017/04/05 Javascript
Vue2.0用户权限控制解决方案的示例
2018/02/10 Javascript
vue实现2048小游戏功能思路详解
2018/05/09 Javascript
vue组件横向树实现代码
2018/08/02 Javascript
详解JavaScript添加给定的标签选项
2018/09/17 Javascript
微信小程序传值以及获取值方法的详解
2019/04/29 Javascript
js实现小时钟效果
2020/03/25 Javascript
[04:39]显微镜下的DOTA2第十三期—Pis卡尔个人秀
2014/04/04 DOTA
深入解析Python中的descriptor描述器的作用及用法
2016/06/27 Python
python爬虫URL重试机制的实现方法(python2.7以及python3.5)
2018/12/18 Python
使用Python批量修改文件名的代码实例
2019/01/24 Python
详解用python写一个抽奖程序
2019/05/10 Python
Python画图高斯分布的示例
2019/07/10 Python
Python爬虫 bilibili视频弹幕提取过程详解
2019/07/31 Python
keras中epoch,batch,loss,val_loss用法说明
2020/07/02 Python
简单了解Django项目应用创建过程
2020/07/06 Python
HTML5 Canvas之测试浏览器是否支持Canvas的方法
2015/01/01 HTML / CSS
LivingSocial英国:英国本地优惠
2019/02/22 全球购物
法院先进个人事迹材料
2014/05/04 职场文书
活动总结范文
2014/08/30 职场文书
2014年驾驶员工作总结
2014/11/18 职场文书
会计工作能力自我评价
2015/03/05 职场文书