PHP 数据对象

添加一个注释

用户捐赠的注释 15 个注释

djlopez at gmx dot de
17 年前
请注意,这

无效
$sth = $dbh->prepare('SELECT name, colour, calories FROM ? WHERE calories < ?');

有效!
$sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ?');

参数不能应用于表名!!
wiserufferto at gmail dot com
3 年前
有点晚了... 但我很老很慢.......
关于扩展 PDOStatement 和 PDO 我发现通过引用发送 PDOExtended 类很有帮助
在父类构造函数的 parent::__construct() 之后
$this->setAttribute(\PDO::ATTR_STATEMENT_CLASS,array('PDOStatementExtended', [&$this]));}

并且在
class PDOStatementExtended extends \PDOStatement
{

protected function __construct
(
\PDO &$PDO,
)
pokojny at radlight dot com
18 年前
我想将 PDO 类扩展为存储数据库使用统计信息,遇到了一些问题。我想统计创建的语句数量以及执行语句数量。因此,PDOStatement 应该指向创建它的 PDO,还要存储统计信息。问题是我不知道 PDO 如何创建 PDOStatement(构造函数参数等),所以创建了这两个类。

<?php
/**
* PHP Document Object plus
*
* PHP Document Object plus is library with functionality of PDO, entirely written
* in PHP, so that developer can easily extend it's classes with specific functionality,
* such as providing database usage statistics implemented in v1.0b
*
* @author Peter Pokojny
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
class PDOp {
protected
$PDO;
public
$numExecutes;
public
$numStatements;
public function
__construct($dsn, $user=NULL, $pass=NULL, $driver_options=NULL) {
$this->PDO = new PDO($dsn, $user, $pass, $driver_options);
$this->numExecutes = 0;
$this->numStatements = 0;
}
public function
__call($func, $args) {
return
call_user_func_array(array(&$this->PDO, $func), $args);
}
public function
prepare() {
$this->numStatements++;

$args = func_get_args();
$PDOS = call_user_func_array(array(&$this->PDO, 'prepare'), $args);

return new
PDOpStatement($this, $PDOS);
}
public function
query() {
$this->numExecutes++;
$this->numStatements++;

$args = func_get_args();
$PDOS = call_user_func_array(array(&$this->PDO, 'query'), $args);

return new
PDOpStatement($this, $PDOS);
}
public function
exec() {
$this->numExecutes++;

$args = func_get_args();
return
call_user_func_array(array(&$this->PDO, 'exec'), $args);
}
}
class
PDOpStatement implements IteratorAggregate {
protected
$PDOS;
protected
$PDOp;
public function
__construct($PDOp, $PDOS) {
$this->PDOp = $PDOp;
$this->PDOS = $PDOS;
}
public function
__call($func, $args) {
return
call_user_func_array(array(&$this->PDOS, $func), $args);
}
public function
bindColumn($column, &$param, $type=NULL) {
if (
$type === NULL)
$this->PDOS->bindColumn($column, $param);
else
$this->PDOS->bindColumn($column, $param, $type);
}
public function
bindParam($column, &$param, $type=NULL) {
if (
$type === NULL)
$this->PDOS->bindParam($column, $param);
else
$this->PDOS->bindParam($column, $param, $type);
}
public function
execute() {
$this->PDOp->numExecutes++;
$args = func_get_args();
return
call_user_func_array(array(&$this->PDOS, 'execute'), $args);
}
public function
__get($property) {
return
$this->PDOS->$property;
}
public function
getIterator() {
return
$this->PDOS;
}
}
?>

这些类具有原始 PDO 和 PDOStatement 对象的属性,它们为 PDOp 和 PDOpStatement 提供功能。
从外部,PDOp 和 PDOpStatement 看起来像 PDO 和 PDOStatement,但也提供所需的信息。
matthew at button-mashers dot net
10 年前
使用预处理语句时,没有官方的 PDO 功能可以向你显示提交给数据库的最终查询字符串,包括你传递的参数。

使用此简单函数进行调试。你传递的值可能与你的预期不同。

<?php
//示例查询字符串
$query = "UPDATE users SET name = :user_name WHERE id = :user_id";

//示例参数
$params = [':user_name' => 'foobear', ':user_id' => 1001];

function
build_pdo_query($string, $array) {
//获取各数组元素的键长度。
$keys = array_map('strlen', array_keys($array));

//按字符串长度对数组排序,以便先替换最长的字符串。
array_multisort($keys, SORT_DESC, $array);

foreach(
$array as $k => $v) {
//对非数字值加上引号。
$replacement = is_numeric($v) ? $v : "'{$v}'";

//替换搜索词。
$string = str_replace($k, $replacement, $string);
}

return
$string;
}

echo
build_pdo_query($query, $params); //UPDATE users SET name = 'foobear' WHERE id = 1001
?>
www.navin.biz
18 年前
以下是扩展 PDO 和 PDOStatement 类的示例

<?php

数据库 扩展 PDO
{
函数
__construct()
{
父级::__construct('mysql:dbname=test;host=localhost', 'root', '');
$this->设置属性(PDO::ATTR_STATEMENT_CLASS, 数组('DBStatement', 数组($this)));
}
}

DBStatement 扩展 PDOStatement
{
公用
$dbh;

保护函数
__construct($dbh)
{
$this->dbh = $dbh;
$this->setFetchMode(PDO::FETCH_OBJ);
}

公共函数
foundRows()
{
$行 = $this->dbh->准备('SELECT found_rows() AS rows', 数组(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE));
$行->执行();
$行数 = $行->获取(PDO::FETCH_OBJ)->;
$行->关闭游标();
返回
$行数;
}
}

?>
paulius_k at yahoo dot com
18 年前
如果您需要从 MSSQL 存储过程中获取输出变量,请尝试以下操作

-- 过程
创建过程 spReturn_Int @err int OUTPUT
AS
设置 @err = 11
GO

$sth = $dbh->准备("执行 spReturn_Int ?");
$sth->bindParam(1, $return_value, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT);
$sth->execute();
print "过程返回 $return_value\n";
shaolin at adf dot nu
18 年前
如果您在使用共享模块重新编译带有 PDO 的 PHP 时遇到问题,请尝试以下操作。

--enable-pdo=shared
--with-pdo-mysql=shared,/usr/local/mysql
--with-sqlite=shared
--with-pdo-sqlite=shared

1. 如果 PDO 作为共享模块构建,则所有 PDO 驱动程序也必须作为
作为共享模块构建。
2. 如果 ext/pdo_sqlite 作为共享模块构建,则 ext/sqlite 也必须
作为共享模块构建。
3. 在扩展条目中,如果 ext/pdo_sqlite 作为共享
模块,php.ini 必须先指定 pdo_sqlite,然后是 sqlite。
Sbastien Gourmand
11 年前
将 prepare() 和 execute() 合并成一个函数,就像 sprintf() 一样。
和 sprintf 一样,我选择使用未命名的参数 (?) ;)

您仍然可以使用重命名的函数进行旧的不安全的查询 ( 未准备 ) :)

<?php
class MyPDO extends PDO{

const
PARAM_host='localhost';
const
PARAM_port='3306';
const
PARAM_db_name='test';
const
PARAM_user='root';
const
PARAM_db_pass='';

public function
__construct($options=null){
parent::__construct('mysql:host='.MyPDO::PARAM_host.';port='.MyPDO::PARAM_port.';dbname='.MyPDO::PARAM_db_name,
MyPDO::PARAM_user,
MyPDO::PARAM_db_pass,$options);
}

public function
query($query){ //secured query with prepare and execute
$args = func_get_args();
array_shift($args); //first element is not an argument but the query itself, should removed

$reponse = parent::prepare($query);
$reponse->execute($args);
return
$reponse;

}

public function
insecureQuery($query){ //you can use the old query at your risk ;) and should use secure quote() function with it
return parent::query($query);
}

}

$db = new MyPDO();
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

$t1 = isset($_GET["t1"])?$_GET["t1"]:1; // need to be securised for injonction
$t2 = isset($_GET["t2"])?$_GET["t2"]:2; // need to be securised for injonction
$t3 = isset($_GET["t3"])?$_GET["t3"]:3; // need to be securised for injonction

$ret = $db->query("SELECT * FROM table_test WHERE t1=? AND t2=? AND t3=?",$t1,$t2,$t3);
//$ret = $db->insecureQuery("SELECT * FROM table_test WHERE t1=".$db->quote($t1));

while ($o = $ret->fetch())
{
echo
$o->nom.PHP_EOL;
}
?>
bart at mediawave dot nl
17 年前
似乎 MySQL 不支持可滚动游标。所以很遗憾,PDO::CURSOR_SCROLL 是无效的。
lkmorlan at uwaterloo dot ca
13 年前
您可能还必须编辑 /etc/freetds.conf。确保 TDS 版本是较新的,例如,“tds version = 8.0”。
Konstantin at Tokar dot ru
16 年前
示例 5
<?php
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(
PDO::ATTR_PERSISTENT => true));
.......
} catch (
Exception $e) {
$dbh->rollBack();
echo
"Failed: " . $e->getMessage();
}
?>

我们必须更改最后两行以捕获连接到数据库的错误

} catch (Exception $e) {
echo "Failed: " . $e->getMessage();
$dbh->rollBack();
}
?>
anton dot clarke at sonikmedia dot com
16 年前
并非所有 PDO 驱动程序都将 LOB 返回为文件流;mysql 5 就是一个示例。因此,从数据库流式传输 MIME 类型对象时,您无法使用 fpassthru。

以下是一个改进的示例,它适用于 mysql 数据库。(在 mysql 5.0.45 和 php 5.2.3 中测试了 FreeBSD v 6.2)

<?php
ob_start
();
$db = new PDO('mysql:host=localhost;dbname=<SOMEDB>', '<USERNAME>', 'PASSWORD');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
ob_clean();
header("Content-Type: $type");
echo
$lob; // fpassthru reports an error that $lob is not a stream so echo is used in place.
ob_end_flush();
?>

请注意缓冲控制的包含。我只在使用“include”、“include_once”、“require”或“require_once”时才需要此元素——我的感觉是这些选项存在一个细微的问题,因为即使是一个空包含文件也会给我造成一个缓冲问题。=== 是的,我确实检查了包含的文件在 <?php ?> 分隔符之外没有虚假空白等! ===
neonmandk at gmail dot com
16 年前
如果您要从 PDO 制作一个 OBJ 行,则可以使用此示例。

$resKampange = $dbc->prepare( "SELECT * FROM Table LIMIT 1" );
$resKampange->execute();
$rowKampange = $resKampange->fetch( PDO::FETCH_OB );

echo $rowKampange->felt1;

顺利:0)
webform at aouie dot website
17 年前
如果您使用 $dbh = new PDO('pgsql:host=localhost;dbname=test_basic01', $user, $pass);,并且会收到以下错误
PHP致命错误:未捕获的异常“PDOException”,消息为“SQLSTATE[08006] [7] 无法连接到服务器:拒绝连接\n服务器是否在主机“localhost”上运行,并接受\n端口 5432 上的 TCP/IP 连接?”
然后,正如在 pg_connect 中指出:https://php.net/manual/en/function.pg-connect.php#38291
******
您应尝试将 host=和 port= 部分从连接字符串中去除。这听起来很奇怪,但这是 Postgre 的“选项”。如果您尚未在 postgresql.conf 中激活 TCP/IP 端口,则 postgresql 不会接受来自 TCP/IP 端口的任何传入请求。如果您在连接字符串中使用 host=,您将通过 TCP/IP 连接到 Postgre,因此它不起作用。如果您将 host= 部分从连接字符串中删除,则您将通过 Unix 域套接字连接到 Postgre,这样更快且更安全,但您无法通过除本地主机以外的任何其他 PC 连接到数据库。
******
此致,
Aouie
uwaterloo@lkmorlan dot ca
14 年前
可从 MSSQL 获取 UTF8 数据

<?php
$db
= new PDO('dblib:host=your_hostname;dbname=your_db;charset=UTF-8', $user, $pass);
?>
To Top