PHP - PDO - 学习/实践

1.应用场景

主要用于在PHP脚本中使用PDO与数据库交互~,同时对比PDO与ODBC,JDBC之间的区别,以及本质。

2.学习/操作

1.文档阅读

PHP: 数据库扩展 - Manual

PHP: PDO - Manual

PHP: PDO 驱动 - Manual

PHP: ODBC and DB2 (PDO) - Manual // PDO_ODBC

PHP PDO | 菜鸟教程  // PHP PDO

MySQL :: Connectors and APIs Manual :: 7.4 MySQL Functions (PDO_MYSQL) // mysql - pdo

What is PHP PDO? How to Install & Use It? | Simplilearn

2.整理输出

2.1 简介

全程: PHP Data Object : PHP数据对象

PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。

实现 PDO 接口的每个数据库驱动可以公开具体数据库的特性作为标准扩展功能。

注意利用 PDO 扩展自身并不能实现任何数据库功能;

必须使用一个 具体数据库的 PDO 驱动 来访问数据库服务。

PDO 提供了一个 数据访问 抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

PDO 提供 数据库 抽象层;它不会重写 SQL,也不会模拟缺失的特性。如果需要的话,应该使用一个成熟的抽象层。

PHP 附带了 PDO。

2.2 创建PDO实例 - 连接数据库

方式一:连接MySQL,使用pdo_mysql 驱动

环境:

Mac + Docker「LNMP」

文档参考:

PHP: 连接与连接管理 - Manual

1. 连接是通过创建 PDO 基类的实例而建立的。不管使用哪种驱动程序,都是用 PDO 类名。

构造函数接收用于指定数据库源(所谓的 DSN)以及可能还包括用户名和密码(如果有的话)的参数。

2. 连接数据成功后,返回一个 PDO 类的实例给脚本,此连接在 PDO 对象的生存周期中保持活动。

要想关闭连接,需要销毁对象以确保所有剩余到它的引用都被删除,可以赋一个 null 值给对象变量。「通常未必只是一个变量」

如果不明确地这么做,PHP 在脚本结束时会自动关闭连接。

示例 #1 连接,执行sql脚本,关闭连接,以及处理连接错误

<?php
try {
    $dbh = new PDO('mysql:host=localhost;dbname=app.test', $user, $pass);

    // 在此使用连接
    foreach($dbh->query('SELECT * FROM test') as $row) {
        print_r($row);
    }

    // 现在运行完成,在此关闭连接 ----- 这里只有pdo实例对象 $dbh,并没有调用$dbh的方法而产生的引用
    $dbh = null;
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}
?>

警告

如果应用程序不在 PDO 构造函数中捕获异常,zend 引擎采取的默认动作是结束脚本并显示一个回溯跟踪,此回溯跟踪可能泄漏完整的数据库连接细节,包括用户名和密码。

因此有责任去显式(通过 catch 语句)或 隐式(通过 set_exception_handler() )地捕获异常。

3. 很多 web 应用程序通过使用到数据库服务的持久连接获得好处。

持久连接在脚本结束后不会被关闭,且被缓存,当另一个使用相同凭证的脚本连接请求时被重用。

持久连接缓存可以避免每次脚本需要与数据库会话时建立一个新连接的开销,从而让 web 应用程序更快。

示例 #2 持久化连接

<?php


$dbh = new PDO('mysql:host=localhost;dbname=test'$user, $passarray(
    PDO::ATTR_PERSISTENT => true
));
?>

注意:

如果想使用持久连接,必须在传递给 PDO 构造函数的驱动选项数组中设置 PDO::ATTR_PERSISTENT

如果是在对象初始化之后PDO::setAttribute() 设置此属性,则驱动程序将不会使用持久连接。

注意:

如果使用 PDO ODBC 驱动 ODBC 库支持 ODBC 连接池(有unixODBC 和 Windows 两种做法;可能会有更多),建议不要使用持久的 PDO 连接,而是把连接缓存留给 ODBC 连接池层处理。

ODBC 连接池在进程中与其他模块共享;「?TBD」

如果要求 PDO 缓存连接,则此连接绝不会被返回到 ODBC 连接池,导致创建额外的连接来服务其他模块。

PHP: ODBC and DB2 (PDO) - Manual // PDO_ODBC

do_odbc.connection_pooling PDO_ODBC有连接池概念,但是TBD

方式二: 使用ODBC连接MySQL -- 暂时还没完成

pdo_ODBC驱动连接MySQL

环境

Mac + 本机PHP 8.1

1. 确认是否已经开启ODBC驱动

2. 启动本机PHP自带的HTTP Server

php -S localhost:8100 -t ./app.test/public

3. 写入脚本

<?php

$hostname = "localhost";
$port = 33060;
$database = "app.test";
$username = "root";
$password = "root";
 
try {
    $pdo = new PDO("odbc:Driver={MySQL ODBC 3.51 Driver};host=$hostname;database=$database;port=$port", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
    $sql = "SELECT * FROM test";
    $stmt = $pdo->query($sql);
    while ($row = $stmt->fetch()) {
        print( $row[0] . "-" . $row[1] . "-" . $row[2] . "\r\n");
    }
} catch (PDOException $e) {
    echo $e->getMessage();
    exit;
}

// close the connection
$dbh = null;

4. 访问 http://localhost:8100/odbc.php

报错信息:

SQLSTATE[01000] SQLDriverConnect: 0 [unixODBC][Driver Manager]Can't open lib 'MySQL ODBC 3.51 Driver' : file not found

原因和解决办法:

TBD

5. 后续补充

2.3 支持的数据库

PHP: 数据库扩展 - Manual

PHP默认已经支持/开启 pdo扩展和pdo_sqlite扩展「驱动」

下面是windows下的支持的数据库驱动列表

  • extension=php_pdo.dll
  • extension=php_pdo_firebird.dll
  • extension=php_pdo_informix.dll
  • extension=php_pdo_mssql.dll
  • extension=php_pdo_mysql.dll
  • extension=php_pdo_oci.dll
  • extension=php_pdo_oci8.dll
  • extension=php_pdo_odbc.dll
  • extension=php_pdo_pgsql.dll
  • extension=php_pdo_sqlite.dll 

Docker容器中,可以看到并不全

其中没有mssql驱动,是因为Microsoft SQL Server只支持在Windows Server系统上运行

官方文档

国外文档截取

Database Name

Driver Name

Cubrid

PDO_CUBRID

FreeTDS / Microsoft SQL Server / Sybase

PDO_DBLIB

Firebird/Interbase 6

PDO_FIREBIRD

IBM DB2

PDO_IBM

IBM Informix Dynamic Server

PDO_INFORMIX

MySQL 3.x/4.x/5.x

PDO_MYSQL

Oracle Call Interface

PDO_OCI

ODBC v3 (IBM DB2, unixODBC and win32 ODBC)

PDO_ODBC

PostgreSQL

PDO_PGSQL

SQLite 3 and SQLite 2

PDO_SQLITE

Microsoft SQL Server / SQL Azure

PDO_SQLSRV

4D

PDO_4

后续补充

...

3.问题/补充

1. 测试相关PDO的属性设置

<?php

// 其中SQL语句,有模拟数据表

$sql = <<<SQL
    SELECT ALL
        c1, -- For result indexing
        c1, c2
    FROM (
        VALUES
            ROW('ID-1', 'Value 1'),
            ROW('ID-2', 'Value 2a'),
            ROW('ID-2', 'Value 2b'),
            ROW('ID-3', 'Value 3')
    ) AS t (c1, c2);

    SQL;

$result = $pdo->query($sql);
print_r($result->fetchAll(PDO::FETCH_UNIQUE));

/*
Gives :
ID-1 => [c1 => ID-1,  c2 => Value 1]
ID-2 => [c1 => ID-2b, c2 => Value 2b]
ID-3 => [c1 => ID-3,  c2 => Value 3]
*/

?>

2. PHP支持数据库连接池吗?

PHP不支持,PHP连接数据库是非常快的(比其他语言的数据库连接方式快很多),一般用直连就行了;

PDO支持连接池,以及PHP 扩展网络引擎Swoole支持数据库连接池

有两种方式:

1. PDO + ODBC // 似乎并不是真正的数据库连接池,而且这样实现的项目似乎很少,网上资源很少

2. PHP + Swoole

均等待实践~~

韩天峰(Rango)的博客 » 基于swoole扩展实现真正的PHP数据库连接池

4.参考

参加文档阅读列表

后续补充

...

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值