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提供了1个使得程序级属性PDO::ATTCR-V_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中的预处理语句,预处理语句的机能是编写翻译3回,多次运行,会在服务器上缓存查询的语法和实践进度,而在服务器和客户端之间传递有转变的列值。能够预防SQL注入,而且实施进程比query()、exec()快。

    1、PDOStatement对象

    query()方法重回的PDOStatement对象是结果集对象,而prepare()方法重回的PDOStatement对象是询问对象,PDOStatement中的全部分子方法如下:

    图片 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() ] )

    叁 、绑定参数与履行

    当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:该参数提必要第1个参数所钦命占位符的值。能够观望多少个”&”符,它需求按引用传递,在组合准备选择存款和储蓄进程使用此办法时能够依照存款和储蓄过程的某部动作修改这些值。因为该参数是按引用传递,所以不得不提供变量作为参数,无法平素提供值。

    $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()方法回去布尔值

    肆 、获取结果

    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:再次来到1个索引为结果集列名的数组

  • PDO::FETCH_BOTH(默许):重临3个目录为结果集列名和以0起先的列号的数组

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

  • PDO::FETCH_CLASS:重回一个请求类的新实例,映射结果集中的列名到类中对应的属性名。要是 fetch_style 包含
    PDO::FETCH_CLASSTYPE(例如:PDO::FETCH_CLASS |
    PDO::FETCH_CLASSTYPE
    ),则类名由第2列的值决定

  • PDO::FETCH_INTO:更新八个被请求类已存在的实例,映射结果集中的列到类中命名的性质

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

  • PDO::FETCH_NUM:再次来到贰个目录为以0发轫的结果集列号的数组

  • PDO::FETCH_OBJ:重回3个属性名对应结果集列名的匿名对象

    $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()

    该措施能够将2个列和一个钦点的变量名绑定,那样每一遍使用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/>';
}

    伍 、大数目对象的存取
    有时候会在数据库中贮存1个交给相比较大的数码(图片、音乐、电影)(当然那种设计不太合理)。PDO运营在bindParam()和bindColumn()调用中通过运用PDO::PARAM_LOB类型代码来选择大型数据类型。PDO::PARAM_LOB告诉PDO将数据映射为流,所以能够选拔PHP粤语件处理函数来操作那种数据。例:

    图片 3

五、事务

 非每一个数据库都援助理工科程师作,由此当第①次打开连接时,PDO
需求在所谓的“自动提交”形式下运作。自动提交情势表示,即便数据库辅助,运营的每一个查询都有它自身的隐式事务,要是数据库不扶助理工科程师作,则尚未。尽管急需1个作业,则必须用 PDO::beginTransaction() 方法来运维。假设底层驱动不帮助理工程师作,则抛出一个PDOException
分外(不管错误处理设置是怎么的,那都以二个严重的不当状态)。一旦开首了政工,可用PDO::commit() 或 PDO::rollBack()来形成,那取决事务中的代码是或不是运营成功。

    PDO
仅在使得层检查是或不是享有事务处理能力
。倘诺某个运行时规格意味着工作不可用,且数据库服务承受请求去运维二个作业,PDO::beginTransaction() 将依然重临 TRUE 而且没有错误。试着在
MySQL 数据库的 MyISAM
数据表中使用工作正是1个很好的例子。

    当脚本甘休或一而再即将被关门时,假使尚有三个未形成的事务,那么
PDO 将自动回滚该工作。

    唯有由此 PDO::beginTransaction() 运行3个政工后,才可能发生自动回滚。假设手动发出一条查询启动工作,
则 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();
}
?>

 

6、贴三个单例类

<?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);
    }
}
?>

相关文章