2012-11-16 14 views
3

PHP mysqli_result類實現了Traversable接口一段時間。 這給像下面這段代碼一些有趣的可能性:PHP mysqli_result:使用帶有fetch_object的Traversable接口

<?php 

$db = new mysqli('...'); 

$result = $db->query('...'); 

foreach($result as $row) { 
    //$row is an associative array containing the fetched values 
} 

現在,我很喜歡這個漂亮多了,但我目前工作的圖書館我想有對象牽強,不關聯陣列。我也希望能夠一類傳遞給它,這樣我就可以創建一個簡單的模型系統,它

對於我擴展它是這樣的:

<?php 

class mysqli_result_extension extends mysqli_result { 

    protected $result_class; 

    public function set_result_class($class) { $this->result_class = $class; } 

    public function function_to_overwrite() { 

     return $this->fetch_object($this->result_class); 
    } 
} 

我的問題,我想問你:

如何從FETCH_ASSOC現在切換fetch_object? 我想覆蓋的可通過接口,以便返回結果使用方法,但它並沒有定義任何(http://php.net/manual/en/class.traversable.php

所以,我需要以覆蓋從FETCH_ASSOC切換到fetch_object和可以到我的$ result_class傳遞給它,以便我能夠做這樣的事:

<?php 

$db = new mysqli_extension('...'); 

$posts = $db->query('select * from posts'); 
//$result is object of type mysqli_result_extension 

$posts->set_result_class('post'); 

foreach($posts as $post) { 
    //$post is an instance of class 'post' 
} 

我不想髒東西,像哈克FETCH_ASSOC覆蓋,只是在它返回對象

謝謝提前爲您提供幫助並輸入

+1

您可以切換到PDO嗎?不知道如何在MySQLi中做到這一點,但很容易做到你想要的PDO。只需設置'PDO :: ATTR_DEFAULT_FETCH_MODE'屬性,並在執行foreach循環時執行適當的提取類型。 – SDC

+0

這將是一個很好的解決方案,如果我也能夠指定結果對象的類。我搜查了PDO的文件,但找不到方法。擴展PDOStatement類的Afaik導致與擴展mysqli_result相同的問題,因爲它也實現了Traversable – Torben

+0

是的,你可以。我將以代碼的形式發佈它。 – SDC

回答

0

找到的接口定義正如我在評論中說,它很容易做的正是你想要什麼PDO。只需設置PDO::ATTR_DEFAULT_FETCH_MODE屬性,並且在執行foreach循環時它將執行適當的提取類型。

您還可以設置PDO::ATTR_STATEMENT_CLASS屬性來定義要使用的類。

$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS); 
$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS,array('classname',$constructorArgs)); 

有關更多信息,請參閱http://php.net/manual/en/pdo.setattribute.php

使用該解決方案,您需要更改每個查詢的ATTR_STATEMENT_CLASS屬性,具體取決於您要實例化的類。

或者,你可以將其設置爲查詢中指定的類名:

$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); 
$stmt = $db->query("SELECT 'classname', * FROM `table` WHERE `id` = 1;"); 

只需將相關的類名添加到您的查詢作爲要選擇的第一個字段。

查看關於此相關問題的其中一個答案In PHP, How do I set default PDO Fetch Class?瞭解更多信息。

+0

非常感謝,這一定會幫助我完成這項工作! 我可能會使用PDO :: FETCH_CLASSTYPE風格,它似乎是最「動態」的方式 – Torben

0
注意:

這是一個內部引擎接口,無法在PHP腳本中實現。必須使用IteratorAggregate或迭代器。在實現擴展Traversable的接口時,請確保在implements子句中的名稱前面列出IteratorAggregateIterator

即你在http://docs.php.net/class.iterator和/或http://docs.php.net/class.iteratoraggregate

+0

所以我需要定義一個擴展的ArrayIterator類,它將獲取的數組轉換爲offsetGet中所需的對象,然後在mysqli_result_extension中實現IteratorAggregate,它將返回getIterator()中$ this的新* Iterator實例? 用iterator我將不得不爲它定義的所有方法,我真的不希望這樣 我不想寫像20點的方法和其他類只是把FETCH_ASSOC成fetch_object 是否有可能一些其他的方式? – Torben

3

的(姑且稱之爲)的mysqli_result遍歷取模式不會受到影響。因此,默認情況下,關聯數組(列名作爲鍵,它的值爲值)就像mysqli_result::fetch_assoc()一樣。

所以這需要自己的Iterator來完成這項工作。那麼Mysqli結果的非foreach迭代是如何傳統的?對,while()循環:

while($row = $result->fetch_assoc()) 
{ 
    ... 
} 

曰:而獲取的方法就不會返回NULL下去。這是創建迭代的常用形式。

對於這種重複我通常使用一個FetchingIterator,它是一個具體迭代器變成了PHP特定Iterator接口(倒帶,有效,當前,關鍵,下一個)成更簡單的一個。簡單的一個是:下一個倒帶,下一個在下一個有效,直到NULL - 這與while循環幾乎相同,可用於類似的工作API,如不推薦使用的mysql或甚至數組(比較array_shift等)。它也類似於不同編程語言中迭代器的其他實現,這裏特別是Java(比較Iterator Design Pattern (Source Making Guide on Design Patterns) article)。

我做了初步的回去年在我的文章Some PHP Iterator Fun (Feb 2012)和一個很大的提高,標準執行本可以發現FetchingIterator in Iterator Garden容易可以做你想做的事概括它。

讓我們看一個示例應用程序:

class ObjectFetchIterator extends FetchingIterator 
{ 
    public function __construct(mysqli_result $result, $class) { 

     parent::__construct(function() use ($result, $class) { 
      return $result->fetch_object($class); 
     }); 
    } 
} 

mysqli_result::fetch_object()方法先前已在while(...)內現在已經搬進的FetchingIterator爲mysqli的結果構造。然後這是一個非常簡單的實現。或者,也可以重寫受保護的fetchNext()方法,但我只注意它,因爲在此不需要。

的使用例子則是非常簡單的:

$db  = new mysqli('...');  
$result = $db->query('...');  
$iterator = new ObjectFetchIterator($result, 'myClass'); 

/* @var $row myClass */ 
foreach ($iterator as $row) 
{ 
    // $row is a myClass now based on fetched values 
} 

這個例子說明,也沒有必要使用PDO爲這聽起來像一個非常懶惰的藉口:更改整個數據庫層僅這個小細節?沒有!情況正好相反:在foreach中使用迭代器允許將代碼從具體數據庫訪問庫中解除耦合到泛型類型(因爲之前也可以使用數組),但是數組遠不是那麼清晰對象類型)。

希望這可以幫助即使答案遲了一點。剛到我的注意這到目前爲止還沒有真正回答。