Thinkphp与Oracle之间的各种问题
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Thinkphp与Oracle之间的各种问题,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3965字,纯文字阅读大概需要6分钟。
内容图文
![Thinkphp与Oracle之间的各种问题](/upload/InfoBanner/zyjiaocheng/556/86380cd2ddcf47a29e12fa5d8e9f48fe.jpg)
Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。 首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是
Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。
首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是,利用Oracle中的MERGE INTO来实现这一点。
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) { //主键值为空时,不插入主键 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))) { // 过滤非标量数据 $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())); }
不支持事务是Thinkphp连接Oracle时的另一个问题,框架作者似乎已经做过适配,但是应该是没有测试,留下一堆bug。DbOracle.class.php中已经有了startTrans,commit,rollback等,稍作修改即可。
Thinkphp对数据库的所有操作最终都是汇集到query或execute上来执行,但这两个函数里放了一句$this->mode = OCI_COMMIT_ON_SUCCESS;活生生的把事务扼杀了,所以,这里先把两个函数里的这句注释掉。
然后,惊人得发现execute()中调用oci_execute时根本没有传入mode!前面辛辛苦苦改mode又是何苦,果断加上oci_execute($stmt, $this->mode)。
接下来才是让事务生效的重头戏。在事务的几个开关函数中加入对mode的修改,在startTrans()中,将mode设为OCI_DEFAULT,commit和rollback中将将mode设为改回OCI_COMMIT_ON_SUCCESS。这三个函数大概就是这样子的:
/** * 启动事务 * @access public * @return void */ public function startTrans() { $this->initConnect(true); if ( !$this->_linkID ) return false; //数据rollback 支持 if ($this->transTimes == 0) { $this->mode = OCI_DEFAULT; } $this->transTimes++; return ; } /** * 用于非自动提交状态下面的查询提交 * @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; } /** * 事务回滚 * @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; }
还有一个头疼的问题就是日期类型转换,我还在寻找一种便捷的方法来解决这个问题。以后再补充上来吧。
本文出自:http://www.chenxuanyi.cn, 原文地址:http://www.chenxuanyi.cn/thinkphp-oracle.html, 感谢原作者分享。
内容总结
以上是互联网集市为您收集整理的Thinkphp与Oracle之间的各种问题全部内容,希望文章能够帮你解决Thinkphp与Oracle之间的各种问题所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。