Thinkphp對(duì)Oracle的支持簡(jiǎn)直弱爆,只做到了基本的操作,就連事務(wù)都不支持。今天來(lái)手動(dòng)改一改DbOracle.class.php,讓它稍微好用一些吧。 首先是insert。原來(lái)的insert應(yīng)該沒(méi)有什么問(wèn)題,但實(shí)際項(xiàng)目中更多的是需要在插入的時(shí)候遇到已存在的記錄則進(jìn)行更新。于是
Thinkphp對(duì)Oracle的支持簡(jiǎn)直弱爆,只做到了基本的操作,就連事務(wù)都不支持。今天來(lái)手動(dòng)改一改DbOracle.class.php,讓它稍微好用一些吧。
首先是insert。原來(lái)的insert應(yīng)該沒(méi)有什么問(wèn)題,但實(shí)際項(xiàng)目中更多的是需要在插入的時(shí)候遇到已存在的記錄則進(jìn)行更新。于是,利用Oracle中的MERGE INTO來(lái)實(shí)現(xiàn)這一點(diǎn)。
public function insert($data, $options = array(), $replace = false) { if (!$replace) { return parent::insert($data, $options, $replace); } $values = $fields = array(); $this->model = $options['model']; $sql_merge = 'MERGE INTO ' . $this->parseTable($options['table']) . ' using (select 1 from dual) ' . ' ON (' . $this->parseValue($data[$options['marge_key']]) . ' is not null and ' . $this->parseValue($data[$options['marge_key']]) . ' = ' . $options['marge_key'] . ')'; //insert foreach ($data as $key => $val) { //主鍵值為空時(shí),不插入主鍵 if ($this->parseKey($key) == $this->parseKey($options['marge_key']) && $val == null ) { } elseif (is_array($val) && 'exp' == $val[0]) { $fields[] = $this->parseKey($key); $values[] = $val[1]; } elseif (is_scalar($val) || is_null(($val))) { // 過(guò)濾非標(biāo)量數(shù)據(jù) $fields[] = $this->parseKey($key); if (C('DB_BIND_PARAM') && 0 !== strpos($val, ':')) { $name = md5($key); $values[] = ':' . $name; $this->bindParam($name, $val); } else { $values[] = $this->parseValue($val); } } } $sql_insert = 'INSERT (' . implode(',', $fields) . ') VALUES (' . implode(',', $values) . ')'; //update if (isset($data[$this->parseKey($options['marge_key'])]) || $data[$this->parseKey($options['marge_key'])] == null ) { unset($data[$this->parseKey($options['marge_key'])]); } $sql_update = 'UPDATE ' . $this->parseSet($data) . $this->parseWhere(!empty($options['where']) ? $options['where'] : '') . $this->parseOrder(!empty($options['order']) ? $options['order'] : '') . $this->parseLimit(!empty($options['limit']) ? $options['limit'] : ''); $sql = $sql_merge . ' WHEN MATCHED THEN ' . $sql_update . ' WHEN NOT MATCHED THEN ' . $sql_insert; return $this->execute($sql, $this->parseBind(!empty($options['bind']) ? $options['bind'] : array())); }
不支持事務(wù)是Thinkphp連接Oracle時(shí)的另一個(gè)問(wèn)題,框架作者似乎已經(jīng)做過(guò)適配,但是應(yīng)該是沒(méi)有測(cè)試,留下一堆bug。DbOracle.class.php中已經(jīng)有了startTrans,commit,rollback等,稍作修改即可。
Thinkphp對(duì)數(shù)據(jù)庫(kù)的所有操作最終都是匯集到query或execute上來(lái)執(zhí)行,但這兩個(gè)函數(shù)里放了一句$this->mode = OCI_COMMIT_ON_SUCCESS;活生生的把事務(wù)扼殺了,所以,這里先把兩個(gè)函數(shù)里的這句注釋掉。
然后,驚人得發(fā)現(xiàn)execute()中調(diào)用oci_execute時(shí)根本沒(méi)有傳入mode!前面辛辛苦苦改mode又是何苦,果斷加上oci_execute($stmt, $this->mode)。
接下來(lái)才是讓事務(wù)生效的重頭戲。在事務(wù)的幾個(gè)開(kāi)關(guān)函數(shù)中加入對(duì)mode的修改,在startTrans()中,將mode設(shè)為OCI_DEFAULT,commit和rollback中將將mode設(shè)為改回OCI_COMMIT_ON_SUCCESS。這三個(gè)函數(shù)大概就是這樣子的:
/** * 啟動(dòng)事務(wù) * @access public * @return void */ public function startTrans() { $this->initConnect(true); if ( !$this->_linkID ) return false; //數(shù)據(jù)rollback 支持 if ($this->transTimes == 0) { $this->mode = OCI_DEFAULT; } $this->transTimes++; return ; } /** * 用于非自動(dòng)提交狀態(tài)下面的查詢提交 * @access public * @return boolen */ public function commit(){ if ($this->transTimes > 0) { $result = oci_commit($this->_linkID); if(!$result){ $this->error(); return false; } $this->mode = OCI_COMMIT_ON_SUCCESS;//陳宣亦 2014.11.09 14:07 $this->transTimes = 0; } return true; } /** * 事務(wù)回滾 * @access public * @return boolen */ public function rollback(){ if ($this->transTimes > 0) { $result = oci_rollback($this->_linkID); if(!$result){ $this->error(); return false; } $this->mode = OCI_COMMIT_ON_SUCCESS;//陳宣亦 2014.11.09 14:07 $this->transTimes = 0; } return true; }
還有一個(gè)頭疼的問(wèn)題就是日期類型轉(zhuǎn)換,我還在尋找一種便捷的方法來(lái)解決這個(gè)問(wèn)題。以后再補(bǔ)充上來(lái)吧。
本文出自:http://www.chenxuanyi.cn, 原文地址:http://www.chenxuanyi.cn/thinkphp-oracle.html, 感謝原作者分享。
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com