针对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 相关文章推荐
第八节 访问方式 [8]
Oct 09 PHP
不用数据库的多用户文件自由上传投票系统(1)
Oct 09 PHP
ThinkPHP中的关联模型注意点
Jun 16 PHP
thinkPHP实现表单自动验证
Dec 24 PHP
PHP计算日期相差天数实例分析
Feb 23 PHP
php实现无限级分类查询(递归、非递归)
Mar 10 PHP
PHP编写登录验证码功能 附调用方法
May 19 PHP
golang与php实现计算两个经纬度之间距离的方法
Jul 22 PHP
CakePHP框架Session设置方法分析
Feb 23 PHP
PHP Socket网络操作类定义与用法示例
Aug 30 PHP
laravel 输出最后执行sql 附:whereIn的使用方法
Oct 10 PHP
php去除数组中为0的元素的实例分析
Nov 17 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
php5数字型字符串加解密代码
2008/04/24 PHP
WIFI万能钥匙密码查询接口实例
2015/09/28 PHP
PHP实现的限制IP投票程序IP来源分析
2016/05/04 PHP
PHP入门教程之面向对象基本概念实例分析
2016/09/11 PHP
php实现跨域提交form表单的方法【2种方法】
2016/10/17 PHP
[原创]PHPCMS遭遇会员投稿审核无效的解决方法
2017/01/11 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
PHP实现图的邻接矩阵表示及几种简单遍历算法分析
2017/11/24 PHP
PHP使用PDO实现mysql防注入功能详解
2019/12/20 PHP
JavaScript的面向对象(二)
2006/11/09 Javascript
js和as的稳定传值问题解决
2013/07/14 Javascript
JS关闭窗口与JS关闭页面的几种方法小结
2013/12/17 Javascript
如何获取网站icon有哪些可行的方法
2014/06/05 Javascript
jQuery异步加载数据并添加事件示例
2014/08/24 Javascript
JS+CSS实现Div弹出窗口同时背景变暗的方法
2015/03/04 Javascript
基于javascript实现全屏漂浮广告
2016/03/31 Javascript
使用Bootstrap框架制作查询页面的界面实例代码
2016/05/27 Javascript
javascript js 操作数组 增删改查的简单实现
2016/06/20 Javascript
浅析Node.js实现HTTP文件下载
2016/08/05 Javascript
Jquery表单验证失败后不提交的解决方法
2016/10/18 Javascript
Vue 页面跳转不用router-link的实现代码
2018/04/12 Javascript
es6 for循环中let和var区别详解
2020/01/12 Javascript
JavaScript装饰者模式原理与用法实例详解
2020/03/09 Javascript
[02:28]DOTA2 2017国际邀请赛小组赛回顾
2017/08/09 DOTA
对于Python的Django框架使用的一些实用建议
2015/04/03 Python
图解python全局变量与局部变量相关知识
2019/11/02 Python
Python基于模块Paramiko实现SSHv2协议
2020/04/28 Python
python 实现 hive中类似 lateral view explode的功能示例
2020/05/18 Python
浅谈keras2 predict和fit_generator的坑
2020/06/17 Python
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
初中毕业典礼演讲稿
2014/09/09 职场文书
思想纪律作风整顿剖析材料
2014/10/11 职场文书
会计简历自我评价
2015/03/10 职场文书
Python-typing: 类型标注与支持 Any类型详解
2021/05/10 Python
python3中apply函数和lambda函数的使用详解
2022/02/28 Python
Java数据结构之堆(优先队列)
2022/05/20 Java/Android