ThinkPHP3.2.3 连接oracle 教程 – ThinkPHP框架

thinkphp讨论区给大家提供一个技术圈交流的平台,您可以在这求助各种技术难题,发布关于thinkphp的招聘,吐槽闲聊心情,分享IT生活的各种欢乐与小烦恼,快来加入我们把!让我们大家共创TP和谐新社区!

来源: ThinkPHP3.2.3 连接oracle 教程 – ThinkPHP框架

一、 操作环境
系统:Windows7 旗舰版 64位
PHP环境:WampServer Version 2.5
ThinkPHP:3.2.3 正式版
Oracle:Orcale_10g 64位版

二、 环境配置
1.打开如图的PHP扩展菜单,在绿色图标上,左键->PHP->PHP扩展,点击php_pdo_oci的扩展,这时候这个WAMP会重启,等待重启后变绿,就表示OK。

2, 再次打开刚才的localhost页面,如果找到如图4的显示,就表示目前PHP已经支持Oracle了。

三、 ThinkPHP配置
1, 把下载好的3.2.3正式版解压,项目中只需要ThinkPHP文件夹,这是核心。

2, 使用IDE新建一个项目,项目的文件夹为刚才的Wamp下的www文件夹,如果个人需要自定义别的文件夹,需要修改apache的配置文件,这里我不修改。
3, 将Thinkphp文件夹拷贝到项目文件夹中,新建一个php文件,命名index.php。
4, IDE中已经有这些文件的显示了,打开index.php,编写如下内容:
. 代码如下:

  1. <?php
  2. define(‘APP_Debug, true);
  3. require ‘./ThinkPHP/ThinkPHP.php’;

复制代码

5, 在浏览器中打开localhost/项目名/index.php,Thinkphp会帮你生成好相关文件和文件夹。
6, 对配置文件进行操作,找到:Conf文件夹下config.php文件,修改如下:
. 代码如下:

  1.     ‘DB_TYPE’ => ‘oracle’, // 数据库类型
  2.     ‘DB_HOST’ => ‘localhost’, // 服务器地址
  3.     ‘DB_NAME’ => ‘test’, //这个是我自己后来建的数据库
  4.     ‘DB_USER’ => ‘test’, // 用户名
  5.     ‘DB_PWD’ => ‘orcl’, // 密码
  6.     ‘DB_PORT’ => ‘1521’, // 端口
  7.     ‘DB_CASE_LOWER’ => true,
  8.     ‘DB_PREFIX’ => ‘ccthink_’, // 数据库表前缀
  9.     ‘DB_CHARSET’=> ‘utf8’,
  10.     ‘DB_SEQUENCE_PREFIX’ => ‘SEQ_’,

复制代码

Oracle数据库和mySQL 的结构不同,一般默认安装的数据库名是orcl,如果你使用了多个数据库监听,那么就要根据具体的监听字段来设置。比如:我本机数据库坚挺是Orcl,同时监听另外一个外网的数据库,监听字符串为Orcl2,那么如果你需要连接这个外网数据库,那么需要写的数据库名就是orcl2。

7, 经过以上的配置,是已经可以连接oracle数据库了,但是在thinkphp的实际操作中有什么注意的地方,且接着往下看。
修改oracle驱动文件 ThinkPHP\Library\Think\Db\Driver\Oracle.class.php

  1. <?php
  2. // +———————————————————————-
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +———————————————————————-
  5. // | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
  6. // +———————————————————————-
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +———————————————————————-
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +———————————————————————-
  11. namespace Think\Db\Driver;
  12. use Think\Db\Driver;
  13. use PDO;
  14. /**
  15.  * Oracle数据库驱动
  16.  */
  17. class Oracle extends Driver{
  18.     private     $table        = ;
  19.     protected   $selectSQL    = ‘SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT  %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%’;
  20.     /**
  21.      * 解析pdo连接的dsn信息
  22.      * @access public
  23.      * @param array $config 连接信息
  24.      * @return string
  25.      */
  26.     protected function parseDsn($config){
  27.         $dsn  =   ‘oci:dbname=//’.$config[‘hostname’].($config[‘hostport’]?‘:’.$config[‘hostport’]:).‘/’.$config[‘database’];
  28.         if(!empty($config[‘charset’])) {
  29.             $dsn  .= ‘;charset=’.$config[‘charset’];
  30.         }
  31.         return $dsn;
  32.     }
  33.     /**
  34.      * 执行语句
  35.      * @access public
  36.      * @param string $str  sql指令
  37.      * @param boolean $fetchSql  不执行只是获取SQL     
  38.      * @return integer
  39.      */
  40.     public function execute($str,$fetchSql=false) {
  41.         $bind = $this->bind; //TODO 新增 修复bug 修复及支持获取自增Id的上次记录 by czw
  42.         $this->initConnect(true);
  43.         if ( !$this->_linkID ) return false;
  44.         $this->queryStr = $str;
  45.         if(!empty($this->bind)){
  46.             $that   =   $this;
  47.             $this->queryStr =   strtr($this->queryStr,array_map(function($val) use($that){ return ‘\”.$that->escapeString($val).‘\”; },$this->bind));
  48.         }
  49.         if($fetchSql){
  50.             return $this->queryStr;
  51.         }
  52.         $flag = false;
  53.         if(preg_match(“/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i”, $str, $match)) {
  54.             //$this->table = C(“DB_SEQUENCE_PREFIX”).str_ireplace(C(“DB_PREFIX”), “”, $match[2]);
  55.             $this->table = C(“DB_SEQUENCE_PREFIX”).str_ireplace(C(“DB_PREFIX”), “”, $match[2]).C(“DB_SEQUENCE_SUFFIX”);//TODO 新增 扩展队列名加后缀 修复bug 修复及支持获取自增Id的上次记录 by czw
  56.             $flag = (boolean)$this->query(“SELECT * FROM user_sequences WHERE sequence_name='” . strtoupper($this->table) . “‘”);
  57.         }
  58.         //释放前次的查询结果
  59.         if ( !empty($this->PDOStatement) ) $this->free();
  60.         $this->executeTimes++;
  61.         N(‘db_write’,1); // 兼容代码        
  62.         // 记录开始执行时间
  63.         $this->Debug(true);
  64.         $this->PDOStatement    =    $this->_linkID->prepare($str);
  65.         if(false === $this->PDOStatement) {
  66.             $this->error();
  67.             return false;
  68.         }
  69.         $this->bind = $this->bind ? $this->bind : $bind;//TODO 新增 修复bug 修复及支持获取自增Id的上次记录 by czw
  70.         foreach ($this->bind as $key => $val) {
  71.             if(is_array($val)){
  72.                 $this->PDOStatement->bindValue($key, $val[0], $val[1]);
  73.             }else{
  74.                 $this->PDOStatement->bindValue($key, $val);
  75.             }
  76.         }
  77.         $this->bind =   array();        
  78.         $result    =    $this->PDOStatement->execute();
  79.         $this->debug(false);
  80.         if ( false === $result) {
  81.             $this->error();
  82.             return false;
  83.         } else {
  84.             $this->numRows = $this->PDOStatement->rowCount();
  85.             if($flag || preg_match(“/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i”, $str)) {
  86.                //$this->lastInsID = $this->_linkID->lastInsertId(); //
  87.                 $this->lastInsID = $this->lastInsertId($this->table);//TODO  修复bug 修复及支持获取自增Id的上次记录 by czw
  88.             }
  89.             return $this->numRows;
  90.         }
  91.     }
  92.     /**
  93.      * TODO
  94.      * 2016-05-09 新增方法 修复bug 修复及支持获取自增Id的上次记录 by czw
  95.      * 取得Oracle最近插入的ID
  96.      * @access public
  97.      */
  98.     public function lastInsertId($sequence = ) {
  99.         try {
  100.             $lastInsID = $this->_linkID->lastInsertId();
  101.         } catch(\PDOException $e) {
  102.             //对于驱动不支持PDO::lastInsertId()的情况
  103.             try {
  104.                 $lastInsID = 0;
  105.                 $seqPrefix = C(“DB_SEQUENCE_PREFIX”) ? C(“DB_SEQUENCE_PREFIX”) : ‘seq_’;
  106.                 $seqSuffix = C(“DB_SEQUENCE_SUFFIX”) ? C(“DB_SEQUENCE_SUFFIX”) : ;
  107.                 $sequence = strtoupper($sequence ? $sequence : $seqPrefix.$this->table.$seqSuffix);
  108.                 $q = $this->query(“SELECT {$sequence}.CURRVAL as t FROM DUAL”);
  109.                 if($q) {
  110.                     $lastInsID = $q[0][‘t’];
  111.                 }
  112.             } catch(\Exception $e) {
  113.                 //print “Error!: ” . $e->getMessage() . “</br>”;
  114.                 //exit;
  115.             }
  116.         }
  117.         return $lastInsID;
  118.     }
  119.     /**
  120.      * 取得数据表的字段信息
  121.      * @access public
  122.      */
  123.      public function getFields($tableName) {
  124.         list($tableName) = explode(‘ ‘, $tableName);
  125.         $result = $this->query(“select a.column_name,data_type,decode(nullable,’Y’,0,1) notnull,data_default,decode(a.column_name,b.column_name,1,0) pk “
  126.                   .“from user_tab_columns a,(select column_name from user_constraints c,user_cons_columns col “
  127.           .“where c.constraint_name=col.constraint_name and c.constraint_type=’P’and c.table_name='”.strtoupper($tableName)
  128.           .“‘) b where table_name='”.strtoupper($tableName).“‘ and a.column_name=b.column_name(+)”);
  129.         $info   =   array();
  130.         if($result) {
  131.             foreach ($result as $key => $val) {
  132.                 $info[strtolower($val[‘column_name’])] = array(
  133.                     ‘name’    => strtolower($val[‘column_name’]),
  134.                     ‘type’    => strtolower($val[‘data_type’]),
  135.                     ‘notnull’ => $val[‘notnull’],
  136.                     ‘default’ => $val[‘data_default’],
  137.                     ‘primary’ => $val[‘pk’],
  138.                     ‘autoinc’ => $val[‘pk’],
  139.                 );
  140.             }
  141.         }
  142.         return $info;
  143.     }
  144.     /**
  145.      * 取得数据库的表信息(暂时实现取得用户表信息)
  146.      * @access public
  147.      */
  148.     public function getTables($dbName=) {
  149.         $result = $this->query(“select table_name from user_tables”);
  150.         $info   =   array();
  151.         foreach ($result as $key => $val) {
  152.             $info[$key] = current($val);
  153.         }
  154.         return $info;
  155.     }
  156.     /**
  157.      * SQL指令安全过滤
  158.      * @access public
  159.      * @param string $str  SQL指令
  160.      * @return string
  161.      */
  162.     public function escapeString($str) {
  163.         return str_ireplace(“‘”, “””, $str);
  164.     }
  165.     /**
  166.      * limit
  167.      * @access public
  168.      * @return string
  169.      */
  170.     public function parseLimit($limit) {
  171.         $limitStr    = ;
  172.         if(!empty($limit)) {
  173.             $limit    =    explode(‘,’,$limit);
  174.             if(count($limit)>1)
  175.                 $limitStr = “(numrow>” . $limit[0] . “) AND (numrow<=” . ($limit[0]+$limit[1]) . “)”;
  176.             else
  177.                 $limitStr = “(numrow>0 AND numrow<=”.$limit[0].“)”;
  178.         }
  179.         return $limitStr?‘ WHERE ‘.$limitStr:;
  180.     }
  181.     /**
  182.      * 设置锁机制
  183.      * @access protected
  184.      * @return string
  185.      */
  186.     protected function parseLock($lock=false) {
  187.         if(!$lock) return ;
  188.         return ‘ FOR UPDATE NOWAIT ‘;
  189.     }
  190.     /**
  191.      * 随机排序
  192.      * @access protected
  193.      * @return string
  194.      */
  195.     protected function parseRand(){
  196.         return ‘DBMS_RANDOM.value’;
  197.     }
  198.     /**
  199.      * 执行查询 返回数据集
  200.      * @access public
  201.      * @param string $str  sql指令
  202.      * @param boolean $fetchSql  不执行只是获取SQL
  203.      * @return mixed
  204.      */
  205.     public function query($str,$fetchSql=false) {
  206.         $this->initConnect(false);
  207.         if ( !$this->_linkID ) return false;
  208.         $this->queryStr     =   $str;
  209.         if(!empty($this->bind)){
  210.             $that   =   $this;
  211.             $this->queryStr =   strtr($this->queryStr,array_map(function($val) use($that){ return ‘\”.$that->escapeString($val).‘\”; },$this->bind));
  212.         }
  213.         if($fetchSql){
  214.             return $this->queryStr;
  215.         }
  216.         //释放前次的查询结果
  217.         if ( !empty($this->PDOStatement) ) $this->free();
  218.         $this->queryTimes++;
  219.         N(‘db_query’,1); // 兼容代码
  220.         // 调试开始
  221.         $this->debug(true);
  222.         $this->PDOStatement = $this->_linkID->prepare($str);
  223.         if(false === $this->PDOStatement){
  224.             $this->error();
  225.             return false;
  226.         }
  227.         foreach ($this->bind as $key => $val) {
  228.             if(is_array($val)){
  229.                 $this->PDOStatement->bindValue($key, $val[0], $val[1]);
  230.             }else{
  231.                 $this->PDOStatement->bindValue($key, $val);
  232.             }
  233.         }
  234.         $this->bind =   array();
  235.         $result =   $this->PDOStatement->execute();
  236.         // 调试结束
  237.         $this->debug(false);
  238.         if ( false === $result ) {
  239.             $this->error();
  240.             return false;
  241.         } else {
  242.             return $this->getResult();
  243.         }
  244.     }
  245.     /**
  246.      * TODO 修复资源(clob)的查找 by czw
  247.      * 获得所有的查询数据
  248.      * @access private
  249.      * @return array
  250.      */
  251.     private function getResult() {
  252.         //返回数据集
  253.        // $result =   $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC);
  254.         while($row=$this->PDOStatement->fetch(PDO::FETCH_ASSOC)){
  255.             $clobFields=$this->detectResource($row);
  256.             if(count($clobFields)>0){
  257.                 $this->retriveResourceRow($row,$clobFields);
  258.             }
  259.             $result[]=$row;
  260.         }
  261.         $this->numRows = count( $result );
  262.         return $result;
  263.     }
  264.     //将资源转换成内容 TODO 修复资源(clob)的查找 by czw
  265.     protected function retriveResourceRow(&$row,$clobFields){
  266.         if(count($clobFields)>0){
  267.             foreach($clobFields as $colName){
  268.                 $row[$colName] =stream_get_contents($row[$colName]);
  269.             }
  270.         }
  271.     }
  272.     //查找资源的字段 TODO 修复资源(clob)的查找 by czw
  273.     protected function detectResource($row){
  274.         $colNames = array();
  275.         foreach ($row as $key=>$val){
  276.             if(is_resource($val)){
  277.                 $colNames[] = $key;
  278.             }
  279.         }
  280.         return $colNames;
  281.     }
  282. }

复制代码

所有表字段通过pdo连接,被thinkphp已经强制转小写了!!
其他的使用方式和之前都一样。

附件 test.zip ( 1.1 MB 下载:188 次 )

分享到: 更多 (0)