Сброс указателя массива в результатах PDO


У меня возникли проблемы с переходом от методов выбора mysql к методам PDO. Я хочу дважды выполнить итерацию по извлеченному массиву, оба раза начиная с нулевой строки. В mysql я бы использовал:

mysql_data_seek($result,0);

Используя методы PDO, я не уверен, как сделать то же самое. Приведенный ниже код показывает, как я пытаюсь это сделать. Первый цикл while работает нормально, но второй цикл while ничего не возвращает. Может кто-нибудь, пожалуйста, сказать мне, где я ошибаюсь?

$pdo = new PDO('mysql:host=' . $host . ';dbname='.$database, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->prepare('SELECT * FROM mytable WHERE active = 1 ORDER BY name ASC');
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();

while($row = $stmt->fetch())
{
    //do something starting with row[0]
}
while($row = $stmt->fetch())
{
    //do something else starting with row[0]
}

Спасибо за вашу помощь.

Author: user1028866, 2012-02-24

6 answers

Сохраните результаты в массив, а затем дважды выполните цикл по этому массиву.

$pdo = new PDO('mysql:host=' . $host . ';dbname='.$database, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->prepare('SELECT * FROM mytable WHERE active = 1 ORDER BY name ASC');
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();

$rows = $stmt->fetchAll();

foreach ($rows as $r) {
    // first run
}

foreach ($rows as $r) {
    // seconds run
}
 25
Author: Marwelln, 2014-06-09 11:59:18
fetch — Fetches the next row from a result set

Поэтому, когда он выходит из первого, когда он уже прибыл к последнему элементу вашего набора результатов, поэтому второй while ничего не возвращает.

Используйте fetchAll, чтобы сохранить все ваши результаты, а затем просмотреть их.

 3
Author: Mouna Cheikhna, 2012-02-24 20:08:25

Согласно руководству по php, вы можете выполнить запрос несколько раз, если вы подготовите объект PDOStatement с помощью PDO::prepare(), вы можете выполнить инструкцию с несколькими вызовами PDOStatement::execute(). Так что ваш код будет выглядеть именно так.

$stmt = $pdo->prepare('SELECT * FROM mytable WHERE active = 1 ORDER BY name ASC');
$stmt->setFetchMode(PDO::FETCH_ASSOC);

//First execute
$stmt->execute();
while($row = $stmt->fetch())
{
    //do something starting with row[0]
}

//Second execute
$stmt->execute();
while($row = $stmt->fetch())
{
    //do something else starting with row[0]
}

Источник: http://php.net/manual/en/pdo.query.php

 3
Author: Cedriga, 2017-03-17 21:15:14

Иногда сохранение результата fetchAll() не является вариантом. Вместо этого вы можете просто клонировать объект pdo перед вызовом fetchAll(), как это.

$pdo_copy = clone $pdo;

$num_rows = count($pdo_copy->fetchAll());

Теперь я все еще могу использовать объект pdo для выполнения таких инструкций, как fetchObject();

 2
Author: Josh Woodcock, 2014-12-29 06:27:55

Вам нужно указать оператору, что он должен быть прокручиваемым, указав PDO::CURSOR_SCROLL в качестве опции в разделе подготовка. А затем вы используете PDO::FETCH_ORI_FIRST, чтобы снова перейти к первому элементу после достижения конца, чтобы вы могли начать все сначала.

Полный код:

$pdo = new PDO('mysql:host=' . $host . ';dbname='.$database, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//Making cursor scrollable
$options = array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
$stmt = $pdo->prepare('SELECT * FROM mytable WHERE active = 1 ORDER BY name ASC',
                $options);

$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();

while($row = $stmt->fetch())
{
    //do something starting with row[0]
}

//For the first row we use PDO::FETCH_ORI_FIRST 
//to get the first element again. This will also 
//move the cursor to that element
$first = true; 
while($row = $stmt->fetch(null, $first ? PDO::FETCH_ORI_FIRST : PDO::FETCH_ORI_NEXT)))
{
    $first = false;
    //do something else starting with row[0]
}
 0
Author: Torge, 2018-05-18 13:50:50
if($stmt->fetchColumn() >= 0)
{
    $stmt->execute(); //Reset cursor
    while($rs = $stmt->fetchObject())
    {
        echo "Data: ".$rs->data;
    }
}
else
{
    echo '0';
}
 -3
Author: user3753956, 2014-09-19 16:41:50