LMLPHP后院

PHP扩展PDO MySQL之PDOStatement::bindParam vs bindValue技术

maybe yes 发表于 2015-11-16 13:27

前些日子将 LBlog 在线体验站点 http://lblog.lmlphp.com/ 搬迁到了 VPS 上,其实已经过去了好几个月了。新的 VPSPHP版本比较高,所以运行的时候会出现提示 mysql 系列的函数过时的 Deprecated 错误。这个错误最简单的办法就是在报错级别那里屏蔽掉,但是这个不是我的风格,我更希望以更好的方式来解决。但是一上班根本没有时间,写个 MysqlPdo Enhance 的类,按照之前 LMLPHP 中 Mysql 驱动类的风格。为此,写 PDO 操作类的时候还专门定义了接口来约束自己的行为,生怕出问题,测试之后证明,完全兼容之前的 Mysql 类,写完花了这么几个月的时间,真的伤不起。

这次写 PDO 驱动类的时候,没有参照其他人的写法,完全看官方文档,结合自己的需要,尽量的简单的实现。其实 PDO 已经是面向对象的风格了,其实并不需要什么驱动类来太多的封装,写这个只是为了更好的兼容项目中的代码。刚开始我看 bindValue 和 bindParam 的时候,文档给我的感觉只是一个是变量,一个是确切的值。到后来才发现一个是引用,一个是普通传参。在测试修改操作的时候,发现数据库最后一个字段和前一个字符串一样,int 类型没有收到影响,可能当时脑子太累的缘故,这个问题竟然搞了好久,第二天才弄清楚是因为在循环的时候使用了 bindParam 导致的。

MysqlPdoEnhance 驱动类已经上传到 LMLPHPLBlog 中,LBlog 已经在初始化实例的时候自动选择对应的驱动类。这次改善使得 LBlog 系统更加优秀,对服务器环境的适应能力更强了。

MysqlPdoEnhance 类延续了 Mysql 类的简单风格,只有一个重量级的 query 方法,自动判断是返回资源还是影响的行数。同时也发现在使用 PDO 操作时,不能很好的做到这一点。因为执行 SELECT 的时候也有影响的行数,这点与一般的常识不一样,一般懂数据库的人都应该知道,SELECT 是不会影响到行的,但是 PDO 中的 rowCount 方法返回的值是选出的行数。所以,因为这个缘故,只能从 SQL 上面做一个简单的判断了,算是不太完美。

附 query 方法节选。


public function query($sql, $params = array()){
    $stmt = $this->db->prepare($sql, array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true));
    if($params){
        foreach ($params as $k => $v){
            if(is_array($v)){
                $value = $v['value'];
                $type = isset($v['type']) ? $v['type'] : false;
                $length = isset($v['length']) ? $v['length'] : false;
                if($type && $length){
                    $stmt->bindValue($k, $value, $type, $length);
                }elseif($type){
                    $stmt->bindValue($k, $value, $type);
                }else{
                    $stmt->bindValue($k, $value);
                }
            }else{
                $stmt->bindValue($k, $v);
            }
        }
    }
    $stmt->execute();
    if(preg_match('/^update|^insert/i', trim($sql))){
        return $stmt->rowCount();
    }else{
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}
相关文章
2024-05-02 06:06:20 1714601180 0.032393