针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例


Posted in PHP onJune 16, 2018

本文实例讲述了针对thinkPHP5框架存储过程bug重写的存储过程扩展类。分享给大家供大家参考,具体如下:

近期用tp5框架调取存储过程发现有bug,借鉴了一些官方的函数、以及找了个mysqli的类把存储过程重新写了个扩展类,下面两个类直接放置项目extend目录的stored(这个文件夹名称请按个人习惯命名)目录下,需要注意的是类增加命名空间namespace stored就OK。

1、mysqli类,此类直接在网上找的,新增一个getAllData()的函数来获取存储过程多条数据集

<?php
namespace stored;
/*
掌握满足单例模式的必要条件
(1)私有的构造方法-为了防止在类外使用new关键字实例化对象
(2)私有的成员属性-为了防止在类外引入这个存放对象的属性
(3)私有的克隆方法-为了防止在类外通过clone成生另一个对象
(4)公有的静态方法-为了让用户进行实例化对象的操作
*/
class mysqli{
  //私有的属性
  private static $dbcon=false;
  private $host;
  private $port;
  private $user;
  private $pass;
  private $db;
  private $charset;
  private $link;
  //私有的构造方法
  protected function __construct($config=array()){
    header('content-type:text/html;charset=utf-8');
    $this->host = $config['hostname'] ? $config['hostname'] : 'localhost';
    $this->port = $config['hostport'] ? $config['hostport'] : '3306';
    $this->user = $config['username'] ? $config['username'] : 'root';
    $this->pass = $config['password'] ? $config['password'] : 'root';
    $this->db = $config['database'] ? $config['database'] : 'zhijian';
    $this->charset=isset($config['charset']) ? $config['charset'] : 'utf8';
    //连接数据库
    $this->db_connect();
    //选择数据库
    $this->db_usedb();
    //设置字符集
    $this->db_charset();
  }
  //连接数据库
  private function db_connect(){
    $this->link=mysqli_connect($this->host,$this->user,$this->pass);
    if(!$this->link){
      echo "数据库连接失败<br>";
      echo "错误编码".mysqli_errno($this->link)."<br>";
      echo "错误信息".mysqli_error($this->link)."<br>";
      exit;
    }
  }
  //设置字符集
  private function db_charset(){
    mysqli_query($this->link,"set names {$this->charset}");
  }
  //选择数据库
  private function db_usedb(){
    mysqli_query($this->link,"use {$this->db}");
  }
  //私有的克隆
  private function __clone(){
    die('clone is not allowed');
  }
  //公用的静态方法
  public static function getIntance(){
    if(self::$dbcon==false){
      self::$dbcon=new self;
    }
    return self::$dbcon;
  }
  //执行sql语句的方法
  public function query($sql){
    $res=mysqli_query($this->link,$sql);
    if(!$res){
      echo "sql语句执行失败<br>";
      echo "错误编码是".mysqli_errno($this->link)."<br>";
      echo "错误信息是".mysqli_error($this->link)."<br>";
    }
    return $res;
  }
  //打印数据
  public function p($arr){
    echo "<pre>";
    print_r($arr);
    echo "</pre>";
  }
  public function v($arr){
    echo "<pre>";
    var_dump($arr);
    echo "</pre>";
  }
  //获得最后一条记录id
  public function getInsertid(){
    return mysqli_insert_id($this->link);
  }
  /**
   * 查询某个字段
   * @param
   * @return string or int
   */
  public function getOne($sql){
    $query=$this->query($sql);
    return mysqli_free_result($query);
  }
  //获取一行记录,return array 一维数组
  public function getRow($sql,$type="assoc"){
    $query=$this->query($sql);
    if(!in_array($type,array("assoc",'array',"row"))){
      die("mysqli_query error");
    }
    $funcname="mysqli_fetch_".$type;
    return $funcname($query);
  }
  //获取一条记录,前置条件通过资源获取一条记录
  public function getFormSource($query,$type="assoc"){
    if(!in_array($type,array("assoc","array","row")))
    {
      die("mysqli_query error");
    }
    $funcname="mysqli_fetch_".$type;
    return $funcname($query);
  }
  //获取多条数据,二维数组
  public function getAll($sql){
    $query=$this->query($sql);
    $list=array();
    while ($r=$this->getFormSource($query,"row")) {
      $list[]=$r;
    }
    return $list;
  }
  /**
   * 定义添加数据的方法
   * @param string $table 表名
   * @param string orarray $data [数据]
   * @return int 最新添加的id
   */
  public function insert($table,$data){
    //遍历数组,得到每一个字段和字段的值
    $key_str='';
    $v_str='';
    foreach($data as $key=>$v){
      if(empty($v)){
        die("error");
      }
      //$key的值是每一个字段s一个字段所对应的值
      $key_str.=$key.',';
      $v_str.="'$v',";
    }
    $key_str=trim($key_str,',');
    $v_str=trim($v_str,',');
    //判断数据是否为空
    $sql="insert into $table ($key_str) values ($v_str)";
    $this->query($sql);
    //返回上一次增加操做产生ID值
    return $this->getInsertid();
  }
  /*
   * 删除一条数据方法
   * @param1 $table, $where=array('id'=>'1') 表名 条件
   * @return 受影响的行数
   */
  public function deleteOne($table, $where){
    if(is_array($where)){
      foreach ($where as $key => $val) {
        $condition = $key.'='.$val;
      }
    } else {
      $condition = $where;
    }
    $sql = "delete from $table where $condition";
    $this->query($sql);
    //返回受影响的行数
    return mysqli_affected_rows($this->link);
  }
  /*
  * 删除多条数据方法
  * @param1 $table, $where 表名 条件
  * @return 受影响的行数
  */
  public function deleteAll($table, $where){
    if(is_array($where)){
      foreach ($where as $key => $val) {
        if(is_array($val)){
          $condition = $key.' in ('.implode(',', $val) .')';
        } else {
          $condition = $key. '=' .$val;
        }
      }
    } else {
      $condition = $where;
    }
    $sql = "delete from $table where $condition";
    $this->query($sql);
    //返回受影响的行数
    return mysqli_affected_rows($this->link);
  }
  /**
   * [修改操作description]
   * @param [type] $table [表名]
   * @param [type] $data [数据]
   * @param [type] $where [条件]
   * @return [type]
   */
  public function update($table,$data,$where){
    //遍历数组,得到每一个字段和字段的值
    $str='';
    foreach($data as $key=>$v){
      $str.="$key='$v',";
    }
    $str=rtrim($str,',');
    //修改SQL语句
    $sql="update $table set $str where $where";
    $this->query($sql);
    //返回受影响的行数
    return mysqli_affected_rows($this->link);
  }
  /**
   * @func: 获取存储过程多条数据集
   * @author: bieanju
   * @return: array
   * @createtime: 2017-12-25
   */
  public function getAllData($sql){
    if (mysqli_multi_query($this->link,$sql)) {
      do {
        if ($result = mysqli_store_result($this->link)) {
          while ($row = mysqli_fetch_assoc($result)) {
            $list[] = $row;
          }
          /*必须释放*/
          mysqli_free_result($result);
        }else{
          return false;
        }
        /*mysqli_next_result($this->link) && mysqli_more_results($this->link)*/
      } while (mysqli_next_result($this->link) && mysqli_more_results($this->link));
    } else {
      return false;
    }
    return $list;
  }
}
?>

2、存储过程调用扩展类库:

<?php
/**
 * 针对存储过程处理类
 * @author: bieanju
 * @createtime: 2017-12-21
 */
namespace stored;
use think\Config;
class procs extends mysqli{
  public $mysqli;
  /*
   * 存储过程数据参数
   * */
  protected $data = [];
  /*
   * 执行语句
   * */
  protected $sql = '';
  public function __construct($type = "mysqli"){
    $config = C("存储过程库配置参数");
    if($type == "mysql"){
      $config = Config::get('database');
    }
    $this->mysqli = new mysqli($config);
  }
  /**
   * 根据参数绑定组装最终的SQL语句 便于调试
   * @access public
   * @param string  $sql 带参数绑定的sql语句
   * @param array   $bind 参数绑定列表
   * @return string
   */
  private function getRealSql($sql, array $bind = [])
  {
    foreach ($bind as $key => $val) {
      $value = is_array($val) ? $val[0] : $val;
      $value = is_string($val) ? "'{$val}'" : $val;
      // 判断占位符
      $sql = is_numeric($key) ?
        substr_replace($sql, $value, strpos($sql, '?'), 1) :
        str_replace(
          [':' . $key . ')', ':' . $key . ',', ':' . $key . ' '],
          [$value . ')', $value . ',', $value . ' '],
          $sql . ' ');
    }
    return rtrim($sql);
  }
  /**
   * @func:存储过程执行并得到数据集
   * @author: bieanju
   * @return: boolean
   * @createtime: 2017-12-22
   */
  protected function procs(){
    $procedure = in_array(strtolower(substr(trim($this->sql), 0, 4)), ['call', 'exec']);
    // 参数绑定
    if ($procedure) {
      $sql = $this->getRealSql($this->sql,$this->data);
      return $this->mysqli->getAllData($sql);
    }
    return false;
  }
  /**
   * @func: 存储过程数据
   * @author: bieanju
   * @return: array
   * @createtime: 2017-12-22
   */
  public function data($data = [])
  {
    $this->data = $data;
    return $this;
  }
  /**
   * @func: 存储过程sql
   * @author: bieanju
   * @return: array
   * @createtime: 2017-12-22
   */
  public function sql($sql = '')
  {
    $this->sql = $sql;
    return $this;
  }
  /**
   * 使用DEMO
  */
  public function demo(){
    return $this->sql("call demo(?,?,?,?,?,?)")->procs();
  }
}
?>

3、最终项目中使用demo:

use stored\procs;
/*用use加载后第一步实例化下存储过程类*/
 $this->procs = new procs("mysqli");
/*第二步调用demo方法并获取数据*/
//$data为给存储过程占位符传递的参数必须为array|[ ]
$this->procs->data($data)->demo();

ok是不是调用很简单、多条存储过程的数据集就此拿到!

希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。

PHP 相关文章推荐
数据库查询记录php 多行多列显示
Aug 15 PHP
php flv视频时间获取函数
Jun 29 PHP
php通过COM类调用组件的实现代码
Jan 11 PHP
PHP取整函数:ceil,floor,round,intval的区别详细解析
Aug 31 PHP
PHP内核探索:变量存储与类型使用说明
Jan 30 PHP
php通过ajax实现双击table修改内容
Apr 28 PHP
推荐5款跨平台的PHP编辑器
Dec 25 PHP
php如何获取文件的扩展名
Oct 28 PHP
PHP中SSO Cookie登录分析和实现
Nov 06 PHP
ThinkPHP实现附件上传功能
Apr 27 PHP
PHP实现可添加水印与生成缩略图的图片处理工具类
Jan 16 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
Mar 27 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
Jun 16 #PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
Jun 16 #PHP
PHP基于rabbitmq操作类的生产者和消费者功能示例
Jun 16 #PHP
PHP7.1实现的AES与RSA加密操作示例
Jun 15 #PHP
PHP观察者模式示例【Laravel框架中有用到】
Jun 15 #PHP
PHP堆栈调试操作简单示例
Jun 15 #PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 #PHP
You might like
php中获取主机名、协议及IP地址的方法
2014/11/18 PHP
PHP上传图片到数据库并显示的实例代码
2019/12/20 PHP
PHP7新增函数
2021/03/09 PHP
学习YUI.Ext第七日-View&amp;JSONView Part Two-一个画室网站的案例
2007/03/10 Javascript
js AspxButton的客户端操作
2009/06/26 Javascript
基于jQuery实现的水平和垂直居中的div窗口
2011/08/08 Javascript
js判断浏览器类型的方法
2013/08/07 Javascript
node.js中的emitter.on方法使用说明
2014/12/10 Javascript
JavaScript闭包详解
2015/02/02 Javascript
探索angularjs+requirejs全面实现按需加载的套路
2016/02/26 Javascript
JS随机洗牌算法之数组随机排序
2016/03/23 Javascript
JS 循环li添加点击事件 (闭包的应用)
2016/12/10 Javascript
Electron autoUpdater实现Windows安装包自动更新的方法
2018/12/24 Javascript
利用angular自动编译andriod APK的绕坑经历分享
2019/03/08 Javascript
jquery分页优化操作实例分析
2019/08/23 jQuery
在vue项目中利用popstate处理页面返回的操作介绍
2020/08/06 Javascript
[03:34]2014DOTA2西雅图国际邀请赛 淘汰赛7月15日TOPPLAY
2014/07/15 DOTA
[00:14]PWL:老朋友Mushi拍VLOG与中国玩家问好
2020/11/04 DOTA
python Django模板的使用方法(图文)
2013/11/04 Python
Python编程实现双链表,栈,队列及二叉树的方法示例
2017/11/01 Python
python 字符串和整数的转换方法
2018/06/25 Python
PyCharm代码提示忽略大小写设置方法
2018/10/28 Python
Python英文文本分词(无空格)模块wordninja的使用实例
2019/02/20 Python
python读取tif图片时保留其16bit的编码格式实例
2020/01/13 Python
Python连接SQLite数据库并进行增册改查操作方法详解
2020/02/18 Python
Python如何使用paramiko模块连接linux
2020/03/18 Python
Urban Outfitters德国官网:美国跨国生活方式零售公司
2018/05/21 全球购物
酒店应聘自荐信
2013/11/09 职场文书
人事专员岗位说明书
2014/07/29 职场文书
组工干部演讲稿
2014/09/02 职场文书
服务明星事迹材料
2014/12/29 职场文书
大学生个人学习总结
2015/02/15 职场文书
会计工作态度自我评价
2015/03/06 职场文书
土建技术员岗位职责
2015/04/11 职场文书
巴黎圣母院读书笔记
2015/06/26 职场文书
Kubernetes中Deployment的升级与回滚
2022/04/01 Servers