如何使用 PDO 在 PHP 中获取结果数组?

问题描述 投票:0回答:3

我只是在阅读了 SQL 注入 攻击后编辑我的搜索脚本。我正在尝试使用 PDO 而不是常规 MySQL 连接从我的脚本中获得相同的功能。所以我一直在阅读有关 PDO 的其他帖子,但我不确定。这两个脚本会提供相同的功能吗?

使用 PDO:

$pdo = new PDO('mysql:host=$host; dbname=$database;', $user, $pass);
$stmt = $pdo->prepare('SELECT * FROM auction WHERE name = :name');
$stmt->bindParam(':name', $_GET['searchdivebay']);
$stmt->execute(array(':name' => $name);

使用常规 MySQL:

$dbhost = @mysql_connect($host, $user, $pass) or die('Unable to connect to server');

@mysql_select_db('divebay') or die('Unable to select database');
$search = $_GET['searchdivebay'];
$query = trim($search);

$sql = "SELECT * FROM auction WHERE name LIKE '%" . $query . "%'";

if(!isset($query)){
    echo 'Your search was invalid';
    exit;
} //line 18

$result = mysql_query($trim);
$numrows = mysql_num_rows($result);
mysql_close($dbhost);

我继续使用常规示例

while($i < $numrows){
    $row = mysql_fetch_array($result);

从数据库创建匹配结果数组。我如何使用 PDO 执行此操作?

php mysql pdo
3个回答
108
投票

看看

PDOStatement.fetchAll
方法。您还可以在迭代器模式中使用
fetch

fetchAll
的代码示例,来自 PHP 文档:

<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* Fetch all of the remaining rows in the result set */
print("Fetch all of the remaining rows in the result set:\n");
$result = $sth->fetchAll(\PDO::FETCH_ASSOC);
print_r($result);

结果:

Array
(
    [0] => Array
        (
            [NAME] => pear
            [COLOUR] => green
        )

    [1] => Array
        (
            [NAME] => watermelon
            [COLOUR] => pink
        )
)

22
投票

可通过三种方式获取 PDO 语句返回的多行。

最简单的方法就是迭代 PDO 语句本身:

$stmt = $pdo->prepare("SELECT * FROM auction WHERE name LIKE ?")
$stmt->execute(array("%$query%"));
// iterating over a statement
foreach($stmt as $row) {
    echo $row['name'];
}

另一种方法是在熟悉的 while 语句中使用 fetch() 方法来获取行:

$stmt = $pdo->prepare("SELECT * FROM auction WHERE name LIKE ?")
$stmt->execute(array("%$query%"));
// using while
while($row = $stmt->fetch()) {
    echo $row['name'];
}

但是对于现代 Web 应用程序,我们应该将数据库交互与输出分开,因此最方便的方法是使用 fetchAll() 方法一次获取所有行:

$stmt = $pdo->prepare("SELECT * FROM auction WHERE name LIKE ?")
$stmt->execute(array("%$query%"));
// fetching rows into array
$data = $stmt->fetchAll();

或者,如果您需要先预处理一些数据,请使用 while 循环并手动将数据收集到数组中:

$result = [];
$stmt = $pdo->prepare("SELECT * FROM auction WHERE name LIKE ?")
$stmt->execute(array("%$query%"));
// using while
while($row = $stmt->fetch()) {
    $result[] = [
        'newname' => $row['oldname'],
        // etc
    ];
}

然后将它们输出到模板中:

<ul>
<?php foreach($data as $row): ?>
    <li><?=$row['name']?></li>
<?php endforeach ?>
</ul>

请注意,PDO 支持许多复杂的获取模式,允许 fetchAll() 以多种不同格式返回数据


0
投票

首先,关于防止在用户输入中潜在使用/滥用通配符的说明。

如果您的用户在其

%
文本中提供任何
_
$query
字符,并且您将其直接传递到准备好的语句中,则这些符号将被解释为具有特殊含义的字符。如果您想确保这些字符在 SQL 中被视为文字字符,那么您需要对它们进行转义。对于可移植的解决方案(跨不同的 SQL 方言),请在 SQL 中手动设置转义字符并将其用于潜在的通配符和转义字符本身。

$query = 'bu%';
$escaped = str_replace(['!', '%', '_'], ['!!', '!%', '!_'], $query);
$stmt = $pdo->prepare("SELECT * FROM auction WHERE name LIKE ? ESCAPE '!'");
$stmt->execute(["%$escaped%"]);

玩我的PHPize 演示

我想提供一些关于可用抓取技术的额外见解。

  • foreach()
    $stmt
    变量上:

    使用

    foreach()
    的优点是不需要在每次迭代时显式调用
    fetch()
    并且它提供了访问第一级索引以及相应行数据的能力。

    每次迭代的行有效负载不仅携带每行的关联元素,还携带包含相同值的索引元素(就像调用
    fetch(PDO::FETCH_BOTH)
    一样)。

    foreach ($stmt as $i => $row) {
        echo "$i: " . var_export($row, true) . "\n";
    }
    

    那么单次迭代的输出将如下所示:

    0: array('id' => 5, 0 => 5, 'name' => 'bu%', 1 => 'bu%')
    

  • fetch()
    循环中调用
    while()


    由于 PDO 的获取模式可以应用于
    fetch()
    调用,因此可以更好地控制可用的行结构。 PHP 手册中列出了这些模式。

    while()
    循环不会直接提供对每行父索引的访问;如果您需要该整数,那么您需要手动声明并递增计数器变量。

    $i = 0;
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "$i: " . var_export($row, true) . "\n";
        ++$i;
    }
    
    0: array('id' => 5, 'name' => 'bu%')
    

    我不会将

    while()
    fetch()
    一起使用,除非我需要更简单的
    foreach()
    样式无法提供的数据。

    • 💩
      while ($row = $stmt->fetch(PDO::FETCH_BOTH)) {
    • 💩
      while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    • 💩
      while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
    • 💩
      while ($row = $stmt->fetch()) {
    • foreach ($stmt as $row) {

  • fetchAll()
    (无循环):

    当有效负载不会在同一函数/方法/层中手动循环时,这是适当/常见的调用。换句话说,在

    fetchAll()
    的签名中调用
    foreach()
    是没有意义的,因为这是双重处理。

    • 💩
      foreach ($stmt->fetchAll(PDO::FETCH_BOTH) as $row) {
    • 💩
      foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
    • 💩
      foreach ($stmt->fetchAll(PDO::FETCH_NUM) as $row) {
    • 💩
      foreach ($stmt->fetchAll() as $row) {
    • foreach ($stmt as $row) {

    干净、可重用的模型方法最常见

    return fetchAll(/*preferred_mode*/);

    var_export($stmt->fetchAll(PDO::FETCH_ASSOC));
    
    array(0 => array('id' => 5, 'name' => 'bu%'))
    
© www.soinside.com 2019 - 2024. All rights reserved.