php的mysql\mysqli\PDO(三)PDO

初稿链接:http://www.orlion.ga/1153/

PDO是千篇一律栽数据库抽象层,不止可以拜mysql还好看其他数据库。

 

一、__construct()

PDO::__construct ( string $dsn [, string $username [, string $password [, array$driver_options ]]] )

    $dsn:通常,一个
DSN 由 PDO
驱动名、紧随其后的冒号、以及可选的驱动程序的数据库连接变量信息,如主机名、端口和多少库名。例:oci:dbname=//localhost:1521/my_db(这种是连接Oracle数据库的数源名)mysql:host=localhost;dbname=testdb(这种是接连mysql服务器的数码源名)。php.ini中好设置DSN信息:pdo.dsn.oraclepdo=”OCI:dbname=//localhost:1521/my_db;charset=UTF-8″;在开创PDO对象时便足以:new
PDO(“oraclepdo”, …);

    $driver_options数组用来指定具体驱动之连接选项,形式是“键=>值”对,一些常用之选项项:

    图片 1

    例:

try{
    $db = newpdo('mysql:host=127.0.0.1;port=3306;dbname=mysql;charset=utf8','user','password',array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ));
}catch(PDOException $pe){
    echo $pe->getMessage();
}

 

若无法加载驱动或连续失败会抛来一个PDOException。

二、setAttribute()、getAttribute()方法

    可以调用setAttribute()方法吗PDO对象设置属性,可以调整PDO的作为与底驱动状态,而getAttribute()可以抱属性,例:

$db->setArrtibute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    Oracle数据库在以空字符串返回给PDO时会将空字符串转为PHP的NULL,但是任何的数据库不这样做,这就牵动了可移植性问题,不过PDO提供了一个驱动程序级属性PDO::ATTR_ORACLE_NULLS,该属性可以呢其它数据让套此作为,此属性设置为TRUE,在获时好用空字符串转为NULL。

 

三、exec()、query()

    当执行长删改操作时尚未返回值可以调用PDO对象的exec方法执行SQL,该方式返回给影响的实施,所以来或会见返回回0,但是执行是打响的,所以判断返回值时利用$affected
=== TRUE。例:

$affected = $db->exec("insert into or_users(user_login, user_pass)values('u1', 'p1')");
if (FALSE === $affected) {
    echo 'Error';
}

   
当行select操作时用query(),该办法返回PDOStatement对象,可以调用PDOStatement对象的rowCount()方法查看返回的行数,例:

$pdostatement = $db->query("select user_login, user_pass from or_users");
foreach ($pdostatement as $row) {
    print_r($row);
}

    函数原型:

public PDOStatement PDO::query ( string $statement )
public PDOStatement PDO::query ( string $statement , int $PDO::FETCH_COLUMN , int $colno )
public PDOStatement PDO::query ( string $statement , int $PDO::FETCH_CLASS , string$classname , array $ctorargs )
public PDOStatement PDO::query ( string $statement , int $PDO::FETCH_INTO , object $object)

四、预处理

    PDO支持因占位符(?)语法将变量绑定到SQL中的事先处理语句,预处理语句之用意是编译一不善,多次运作,会以服务器上缓存查询的语法和行过程,而在服务器和客户端里传递出变动的列值。可以预防SQL注入,而且实施进度较query()、exec()快。

    1、PDOStatement对象

    query()方法返回的PDOStatement对象是结果集对象,而prepare()方法返回的PDOStatement对象是查询对象,PDOStatement中的合分子方法如下:

    图片 2

    2、准备语句

    重复执行一个sql语句只不过每次执行之参数有或两样,这时用预处理语句效率最高。PDO有点儿栽占位符语法”命名参数”:

$db->prepare("insert into or_users(user_login, user_pass)values(:user_login, :user_pass)");

    “问号参数”:

$db->prepare("insert into or_users(user_login, user_pass)values(?, ?)");

    prepare()方法返回PDOStatement类对象,原型:

public PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] )

    3、绑定参数与实践

    当SQL准备好之后下一致步就是是为SQL绑定参数了,可以通过PDOStatement对象的bindParam()方法把参数绑定到占位符上:

bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] )

    $parameter:参数标识符。对于下命名占位符的先处理语句,应是近乎 :name 形式之参数曰。对于利用问号占位符的先行处理语句,应是坐1起索引的参数位置。

    &$variable:该参数提供给第一单参数所指定占位符的价值。可以见见一个”&”符,它要依照引用传递,在重组准备采取存储过程使用这个方法时可以依据存储过程的某动作修改是价值。因为该参数是遵照引用传递,所以只好提供变量作为参数,不克直接提供价值。

    $data_type:为当下绑定的参数设置数据类型。可选值:

PDO::PARAM_BOOL: 代表boolean数据类型
PDO::PARAM_NULL: 代表SQL中NULL类型
PDO::PARAM_INT: 代表SQL中INTEGER数据类型
PDO::PARAM_STR: 代表SQL中CHAR、VARCHAR和其他字符串数据类型
PDO::PARAM_LOB: 代表SQL中大对象数据类型。
PDO::PARAM_STMT: 代表PDOStatement对象类型
PDO::PARAM_INPUT_OUTPUT: 专为存储过程使用的数据类型,可以在过程执行后修改

    $length: 可挑选,数据类型的长。为标志参数是一个囤积过程的
OUT 参数,必须旗帜鲜明地设置是尺寸。

    $driver_options: 可选。

    例:

$sql = 'insert into or_users(user_login, user_pass)values(:user_login, :user_pass)';
$stmt = $this->conn->prepare($sql);
$user_login = 'u2';
$user_pass = 'p2';
// $stmt->bindParam(':user_login', 'u2');这种方式是错的,参数不能是具体的值只能是变量
$stmt->bindParam(':user_pass', $user_login);// 这种是正确的
$stmt->bindParam(':user_pass', $user_pass);
$stmt->execute();

// 下面可以改变变量的值继续插入
$user_login = 'u3';
$user_pass = 'p3';
$stmt->execute();

    另外还有同种植更高效的计:

$sql = 'insert into or_users(user_login, user_pass)values(:user_login, :user_pass)';
$stmt = $this->conn->prepare($sql);
$stmt->execute(array(':user_login' => 'u3', ':user_pass' => 'p3'));   

    execute()方法返回布尔值

    4、获取结果

    query()与prepare()+execute()返回的结果是同一的,都用通过PDOStatement对象的方法将结果遍历出来。

    (1)fetch()方法

    原型:

mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] )

    该措施返回结果集的时推行记录并拿结果集指针指向下一行,当到结果集末尾的时光回来FALSE.

    $fetch_style:控制下一行如何回到给调用者,此值必须是 PDO::FETCH_** 系列常量中之一个,缺省为PDO::ATTR_DEFAULT_FETCH_MODE 的值
(默认为 
PDO::FETCH_BOTH* )

    

  • PDO::FETCH_ASSOC:返回一个索引为结果集列名的数组

  • PDO::FETCH_BOTH(默认):返回一个目为结果集列名和以0开始的列号的数组

  • PDO::FETCH_BOUND:返回 TRUE ,并分配结果集中之列值给PDOStatement::bindColumn() 方法绑定的
    PHP 变量。

  • PDO::FETCH_CLASS:返回一个请求求类的初实例,映射结果集中之列名到类似吃对应的属于性名。如果 fetch_style 包含
    PDO::FETCH_CLASSTYPE(例如:PDO::FETCH_CLASS |
    PDO::FETCH_CLASSTYPE
    ),则类名由第一排的价决定

  • PDO::FETCH_INTO:更新一个被呼吁求类已在的实例,映射结果集中之列到类吃命名的属性

  • PDO::FETCH_LAZY:结合使用 PDO::FETCH_BOTH 和 PDO::FETCH_OBJ,创建供用来聘的对象变量名

  • PDO::FETCH_NUM:返回一个目为以0开始的结果集列号的数组

  • PDO::FETCH_OBJ:返回一个属于性名对应结果集列名的匿名对象

    $cursor_orientation:可选,用来确定目标是一个不过滚动的游标时应取得哪一行。

    $cursor_offset:可选,整数值,表示如果落的行相对于目前游标位置的舞狮。

    

    (2)fetchAll()方法

    该方式同样次拿走结果集中具有数据赋给返回的数组:

array PDOStatement::fetchAll ([ int $fetch_style [, mixed $fetch_argument [, array$ctor_args = array() ]]] )

    $fetch_style:控制返回数组的情节似 PDOStatement::fetch() 文档中记载的一模一样。默认为PDO::ATTR_DEFAULT_FETCH_MODE 的值(
其缺乏省值为 PDO::FETCH_BOTH )

思念使赶回一个带有结果集中单独一列所有值的一再组,需要指定 PDO::FETCH_COLUMN 。通过点名 column-index 参数获取想使的排列。

想只要得到结果集中单独一列的绝无仅有值,需要用 PDO::FETCH_COLUMN 和 PDO::FETCH_UNIQUE 按位或。

怀念只要回来一个冲指定列管价值分组后底涉数组,需要用 PDO::FETCH_COLUMN 和PDO::FETCH_GROUP 按位或。

    $fetch_argument:可选,是一个整数索引,当在fetchAll()方法的率先只参数中指定PDO::FETCH_COLUMN值时,从结果集中返回经过该参数提供的目所指定列的富有值。

    

    (3)setFetchMode()

    为报句设置默认的抱模式。

    (4)bindColumn()

    该法可将一个排列和一个点名的变量名绑定,这样每次用fetch方法获得各行记录时,会自动将相应的列值付给该变量,但必须是在fetch()方法的第一独参数设置为PDO::FETCH_BOTH值时,原型:

bool PDOStatement::bindColumn ( mixed $column , mixed &$param [, int $type [, int $maxlen [,mixed $driverdata ]]] )

    $column:可以以整数的列偏移位置索引(索引值于1初步),或是列的名号字符串

    $param:需要传递一个援,所以要提供一个变量号称

    $type:可选,通过设置变量的种类来限制变量值,该参数支持之值和bindParam()方法同样。

    例:

$sql = 'select user_login, user_pass from or_users';
$stmt = $db->prepare($sql);
$stmt->execute();
$stmt->bindColumn(1, $user_login);
$stmt->bindColumn('user_pass', $user_pass);

while($row = $stmt->fetch()) {
    echo $user_login . $user_pass . '<br/>';
}

    5、大数据对象的存取
    有时候会当数据库被蕴藏一个付比较好之数码(图片、音乐、电影)(当然这种计划无绝合理)。PDO运行于bindParam()和bindColumn()调用中经采用PDO::PARAM_LOB类型代码来使用大型数据类型。PDO::PARAM_LOB告诉PDO将数据映射为流动,所以可以用PHP中文件处理函数来操作这种数据。例:

    图片 3

五、事务

 非每种数据库都支持工作,因此当第一次等打开连接时,PDO
需要在所谓的“自动提交”模式下运作。自动提交模式表示,如果数据库支持,运行的每个查询都来其和谐的隐式事务,如果数据库不支持工作,则无。如果欲一个事务,则必须用 PDO::beginTransaction() 方法来启动。如果底层驱动不支持工作,则弃来一个
PDOException
异常(不管错误处理设置是怎的,这还是一个严重的错误状态)。一旦开了作业,可用PDO::commit() 或 PDO::rollBack()来好,这取决于事务中的代码是否运行成功。

    PDO
仅在使层检查是不是富有事务处理能力
。如果某些运行时规格意味着工作不可用,且数据库服务接受请求去启动一个事务,PDO::beginTransaction() 将仍返回 TRUE 而且没有不当。试着在
MySQL 数据库的 MyISAM
数据表中使用工作就是一个那个好的例证。

    当脚论了或连即将于关时,如果还有一个勿成功的作业,那么
PDO 将电动回滚该事务。

    只有由此 PDO::beginTransaction() 启动一个政工后,才可能发自动回滚。如果手动发出同样长达查询启动工作,
则 PDO 无法理解,从而在必要时不能够开展回滚。

    贴单PHP手册中举的例子:

<?php
try {
  $dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2', 
      array(PDO::ATTR_PERSISTENT => true));
  echo "Connected\n";
} catch (Exception $e) {
  die("Unable to connect: " . $e->getMessage());
}

try {  
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $dbh->beginTransaction();
  $dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
  $dbh->exec("insert into salarychange (id, amount, changedate) 
      values (23, 50000, NOW())");
  $dbh->commit();
  
} catch (Exception $e) {
  $dbh->rollBack();
  echo "Failed: " . $e->getMessage();
}
?>

 

六、贴一个单例类

<?php
namespace DB;

use PDO;
use PDOException;
use Exception;

class DBPDO
{
    const DB_USER = 'root';

    const DB_PWD  = '';

    const DB_DSN = 'mysql:host=127.0.0.1:3306;dbname=orlion';

    private static $DB_OPT = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ORACLE_NULLS => TRUE);

    private $conn;

    private static $_instance = null;

    private function __construct()
    {
        $this->conn = new PDO(self::DB_DSN, self::DB_USER, self::DB_PWD, self::$DB_OPT);
    }

    private function __clone()
    {

    }

    public static function getInstance()
    {
        if (is_null(self::$_instance) || !self::$_instance instanceof self) {
                try {
                self::$_instance = new self();
            } catch (PDOException $pe) {
                // 这里应该抛一个自定义异常以便上层处理
                throw new Exception('Could not connect to database:' . self::DB_DSN);
            }
        }

        return self::$_instance;
    }

    public function query($sql)
    {
        return $this->conn->query($sql);
    }

    public function update($sql)
    {
        return $this->conn->exec($sql);
    }

    public function __destruct()
    {
        unset($this->conn);
    }
}
?>

相关文章