2008-11-10 23 views
14

Tôi đang cố gắng viết một trình lặp cho các kết quả từ một câu lệnh PDO nhưng tôi không thể tìm thấy bất kỳ cách nào để tua lại hàng đầu tiên. Tôi muốn tránh chi phí gọi hàm fetchAll và lưu trữ tất cả dữ liệu kết quả.Có thể tua lại kết quả PDO không?

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

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

Có cách nào để đặt lại tuyên bố hoặc tìm kiếm hàng đầu tiên không?

Trả lời

10

Tôi khá chắc chắn đây là cơ sở dữ liệu phụ thuộc. Do đó, đó là điều bạn nên tránh. Tuy nhiên, tôi nghĩ bạn có thể đạt được những gì bạn muốn bằng cách bật buffered queries. Nếu điều đó không hiệu quả, bạn luôn có thể kéo kết quả vào một mảng với fetchAll. Cả hai giải pháp đều có ý nghĩa đối với hiệu suất ứng dụng của bạn, vì vậy hãy suy nghĩ kỹ về nó, nếu kết quả là lớn.

1

Có thể bạn sẽ muốn xem xét một số lớp SPL PHP có thể được mở rộng để cung cấp truy cập giống như mảng cho các đối tượng.

+2

PdoStatement đã triển khai Traversable – troelskn

8

xem slide 31 from this presentation, bạn có thể thực hiện $statement->rewind() nếu nó áp dụng cho truy vấn được đệm. Nếu bạn sử dụng mysql, bạn có thể bắt chước các truy vấn đệm bằng cách sử dụng PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:

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

@NoahGoodrich chỉ bạn SPL. Dưới đây là ví dụ luôn hoạt động:

$it = new ArrayIterator($stmt->fetchAll()); 
9

Lớp nhỏ này tôi đã viết kết thúc tốt đẹp một PDOStatement. Nó chỉ lưu trữ dữ liệu được tìm nạp. Nếu điều này không hoạt động, bạn có thể di chuyển bộ nhớ cache để đọc và ghi vào một tệp.

// 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); 
     } 
    } 
} 
0

Đã hỏi một thời gian dài trước đây nhưng hiện có giải pháp khác.

Phương thức PDOStatement::fetch() có thể nhận tham số thứ hai, hướng con trỏ, với một trong số PDO::FETCH_ORI_* hằng số. Các tham số này chỉ hợp lệ nếu PDOStatement được tạo với thuộc tính PDO::ATTR_CURSORPDO::CURSOR_SCROLL.

Bằng cách này, bạn có thể điều hướng như sau.

$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 

Thông tin thêm trong docsPDO predefined constants.

Lưu ý: sử dụng PDO::FETCH_BOTH vì là mặc định, chỉ cần tùy chỉnh nó cho dự án của bạn.

Các vấn đề liên quan