Можно ли перемотать результат PDO? - PullRequest
14 голосов
/ 10 ноября 2008

Я пытаюсь написать итератор для результатов из оператора PDO, но не могу найти способ перемотки на первую строку. Я хотел бы избежать накладных расходов на вызов fetchAll и сохранение всех данных результатов.

// first loop works fine
foreach($statement as $result) {
    // do something with result
}

// but subsequent loops don't
foreach($statement as $result) {
    // never called 
}

Есть ли способ сброса оператора или поиска в первой строке?

Ответы [ 5 ]

10 голосов
/ 10 ноября 2008

Я уверен, что это зависит от базы данных. Из-за этого вам следует избегать этого. Тем не менее, я думаю, что вы можете достичь того, что вы хотите, включив буферизованных запросов . Если это не сработает, вы всегда можете получить результат в массив с fetchAll. Оба решения влияют на производительность ваших приложений, поэтому подумайте дважды, если наборы результатов велики.

9 голосов
/ 14 июня 2013

Этот маленький класс, который я написал, оборачивает PDOStatement. Он только хранит данные, которые выбираются. Если это не работает, вы можете переместить кэш для чтения и записи в файл.

// Wrap a PDOStatement to iterate through all result rows. Uses a 
// local cache to allow rewinding.
class PDOStatementIterator implements Iterator
{
    public
        $stmt,
        $cache,
        $next;

    public function __construct($stmt)
    {
        $this->cache = array();
        $this->stmt = $stmt;
    }

    public function rewind()
    {
        reset($this->cache);
        $this->next();
    }

    public function valid()
    {
        return (FALSE !== $this->next);
    }

    public function current()
    {
        return $this->next[1];
    }

    public function key()
    {
        return $this->next[0];
    }

    public function next()
    {
        // Try to get the next element in our data cache.
        $this->next = each($this->cache);

        // Past the end of the data cache
        if (FALSE === $this->next)
        {
            // Fetch the next row of data
            $row = $this->stmt->fetch(PDO::FETCH_ASSOC);

            // Fetch successful
            if ($row)
            {
                // Add row to data cache
                $this->cache[] = $row;
            }

            $this->next = each($this->cache);
        }
    }
}
9 голосов
/ 10 ноября 2008

см. слайд 31 из этой презентации , вы можете сделать $statement->rewind(), если он применяется к буферизованному запросу. Если вы используете mysql, вы можете эмулировать буферизованные запросы, используя PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);

@ NoahGoodrich указал тебе на спл. Вот пример, который всегда работает:

$it = new ArrayIterator($stmt->fetchAll());
1 голос
/ 10 августа 2016

Спросили давным-давно, но в настоящее время есть другое решение.

Метод PDOStatement::fetch() может получить второй параметр, ориентацию курсора, с одной из PDO::FETCH_ORI_* констант. Эти параметры действительны только если PDOStatement созданы с атрибутом PDO::ATTR_CURSOR как PDO::CURSOR_SCROLL.

Таким образом, вы можете перемещаться следующим образом.

$sql = "Select * From Tabela";
$statement = $db->prepare($sql, array(
    PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
));
$statement->execute();
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT);  // return next
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_PRIOR); // return previous
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST); // return first
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_LAST);  // return last
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $n); // return to $n position
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_REL, $n); // return to $n position relative to current

Дополнительная информация в документах и Предопределенные константы PDO .

Примечание: используется PDO::FETCH_BOTH, потому что это значение по умолчанию, просто настройте его для своего проекта.

1 голос
/ 10 ноября 2008

Возможно, вы захотите взглянуть на некоторые классы PHP SPL, которые можно расширить для обеспечения доступа к объектам в виде массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...