2010-07-26 1 views
3

PDOStatement을 확장하고 fetch() 메서드를 timestamp 및 배열 형식의 값을 PostgreSQL에서 DateTime 및 기본 배열로 변형했습니다. 이 의도 한대로 작동하지만 foreach 문을 사용할 때 동작을 재정의 할 수 없습니다.foreach를 사용하여 가져올 때 PDO에 대해 fetch()를 재정의합니다.

ArrayAccess, IteratorAggregate 및 Countable을 구현하는 객체에 행을 반환하여이를 해결했습니다. 그러나 나는 그 해결책에 만족하지 않고 단지 순수한 어레이를 원한다.

예 :

 
class ExtendedStatement extends PDOStatement { 
    protected function __construct() { 
     $this->setFetchMode(PDO::FETCH_ASSOC); 
    } 
    public function fetch(
     $fetch_style = PDO::FETCH_ASSOC, 
     $cursor_orientation = PDO::FETCH_ORI_NEXT, 
     $cursor_offset = 0) 
    { 
     $r = parent::fetch($fetch_style, $cursor_orientation, $cursor_offset); 
     if (is_array($r)) { 
      $r["extradata"] = TRUE; 
     } 
     return $r; 
    } 
} 
$db = new PDO("sqlite::memory:"); 
$db->setAttribute(
    PDO::ATTR_STATEMENT_CLASS, array("ExtendedStatement", array($db))); 
$db->exec("CREATE TABLE example(id INTEGER PRIMARY KEY, name VARCHAR)"); 
$db->exec("INSERT INTO example(name) VALUES('test')"); 

// This is what is does 
$s = $db->prepare("SELECT * FROM example"); 
$s->execute(); 
foreach ($s as $r) { 
    var_dump($r); 
} 
$s->closeCursor(); 

// This is how I want it to be 
$s = $db->prepare("SELECT * FROM example"); 
$s->execute(); 
while ($r = $s->fetch()) { 
    var_dump($r); 
} 
$s->closeCursor(); 

// This is how I want it to be 
$s = $db->prepare("SELECT * FROM example"); 
$s->execute(); 
var_dump($s->fetch()); 
$s->closeCursor(); 

출력 :

 
array(2) { 
    ["id"]=> 
    string(1) "1" 
    ["name"]=> 
    string(4) "test" 
} 
array(3) { 
    ["id"]=> 
    string(1) "1" 
    ["name"]=> 
    string(4) "test" 
    ["extradata"]=> 
    bool(true) 
} 
array(3) { 
    ["id"]=> 
    string(1) "1" 
    ["name"]=> 
    string(4) "test" 
    ["extradata"]=> 
    bool(true) 
} 
+0

기대 되는가? 'fetch'를 오버라이드했다면, 항상 "올바르게"작동해야합니다. – Charles

+0

예를 들어 업데이트되었습니다. – runfalk

+0

foreach를'while ($ r = $ s-> fetch()) {'로 대체하면 정상적으로 작동합니까? 또한,'parent :: fetch' 호출에 의해 반환되는 결과는 배열이 아니어도 좋으며, null 일 수 있음을 명심하십시오. 아마'is_array' 체크 나 비슷한 것을 추가해야합니다. – Charles

답변

3

PDOStatement 클래스는 내장 된 내부 전용 Traversable 인터페이스를 구현합니다. 구현하는 반복자는 public PDOStatement::fetch() 메서드를 우회합니다.

+0

나는 이것을 이미 깨달았지만 아직도 어떤 식 으로든 해킹하고 싶다. 나는 Iterator를 구현하는 아이디어를 가지고 있었지만 더 나은 솔루션을 기대하면서 그것을 포기했다. – runfalk

+0

@antennen : 음, 정말로 세 가지 선택이 있습니다 : 1) 패치'ext/pdo/pdo_stmt.c', 2) 대신'while'을 사용하십시오, 3) 당신 만의 반복기를 구현하십시오. 그럼에도 불구하고 http://bugs.php.net에서 버그를 신고하는 것이 좋습니다. public 인'fetch()'메소드를 호출하는 것이 합리적인 것처럼 보입니다. –

+0

버그보고 : http://bugs.php.net/bug.php?id=52444. 나는 지금 당장 iterator 접근법을 시도 할 것이다. – runfalk

-1

내가 이런 걸 사용

$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 
$sql = 'select * from table'; 
$stmt = $db->prepare($sql); 
$stmt->execute(); 

while($row = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) 
{ 
    // do stuff 
} 

그래서 당신이해야 할 유일한 것은 몇 가지 옵션 : 설정

예상대로 작업을 수행하고, 작동하지 않는 몇 가지 코드를 보여줄 수
+0

그의 질문에있는 예제에서 그는 이미 이런 종류의 코드를 가지고 있기 때문에 나는 그 가능성을 알고 있다고 확신합니다. –

관련 문제