2012-09-03 165 views
8

我正在使用Propel 1.6,我不確定如何從propel對象集合中獲取對象(給定其「id」屬性值)。我在Propel的文檔中找不到直接的答案(PropelCollection methods似乎不適用?)。例如: 可以說,我有以下模式的「人」表:如何通過propel對象集合中的「id」獲取對象?

<table name="person"> 
    <column name="id" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/> 
    <column name="name" type="VARCHAR" size="100" required="true"/> 
</table> 

我做下面的查詢得到「人」對象的集合:

$persons = PersonQuery::create()->find(); 

然後,我希望找到具有給定「id」的「Person」對象(例如,具有「id = 3」的「Person」),,而不向數據庫提出新的查詢。我該怎麼做?

$persons->get(...?)? 

換句話說,我不想做的事:

$personX = PersonQuery::create()->findOneById(3); 

語境:

我想阻止使數據庫查詢來提高性能。該聲明是要插入foreach語句,否則會導致大量的數據庫連接中,如下所示:

foreach ($books as $book) { 
    $book['author_name'] = PersonQuery::create()->findOneById($book['author_id'])->getName(); 
} 

回答

4

好了,不會是非常有效的,但你可以去通過收集找到它。

$persons = PersonQuery::create()->find(); 
foreach ($persons as $person) 
{ 
    if (3 == $person->getId()) 
    { 
    break; 
    } 
} 

// now you have your person with id = 3 
var_dump($person->getId()); 
+1

你可以用'array_filter做一個更優雅的方式()':-) – Florent

+0

@ j0k:我試着以避免foreach循環,但我想,如你所說,我無法避免它。我認爲循環進行仍然比創建多個數據庫連接更有效率。感謝您的回答! – RayOnAir

+1

@Florent:我不知道如何在這種情況下實現[array_filter](http://php.net/manual/en/function.array-filter.php)函數,但我會調查...謝謝! – RayOnAir

3

由於行走不緩存正確的查詢結果,你需要遍歷集合(如@ j0k說)。代替使用foreach循環,您可以調用array_filter傳遞閉包(使用PHP 5.3)。

// Request the persons 
$persons = PersonQuery::create()->find(); 

// Filter the persons whose ID equals 3 
$filteredPersons = array_filter($persons, function ($person) { 
    return 3 === $person->getId(); 
}); 

// Get the first result 
$person = empty($filteredPersons) ? null : $filteredPersons[0]; 

如果確定該人會發現,你也可以寫(與PHP 5.4)以下行:

// Filter the person whose ID equals 3 
$person = array_filter($persons, function ($person) { 
    return 3 === $person->getId(); 
})[0]; 
+0

感謝您使用array_filter共享替代解決方案!與使用foreach循環相比,此解決方案從性能角度來看會更好嗎?如果是這樣,你可以分享背後的直覺嗎? – RayOnAir

+1

在PHP 5.4中,'foreach'比'array_filter()'快3倍。此外,使用'foreach',你可以在找到你的條目時'打破'。但在我看來'array_filter()'更具美感。 – Florent

+0

我會記住它的。謝謝! – RayOnAir

2

,如果你設置的Propel :: isInstancePoolingEnabled()爲真(這是默認情況下),那麼你可以

// Request the persons 
$persons = PersonQuery::create()->find(); 
// get person from pool 
$person = PersonPeer::getInstanceFromPool(3); 

對不起,我的英語。

7

另一種選擇,特別是如果你需要搜索幾次是ID使用$來獲得對象數組收藏 - > getArrayCopy( 'ID')。

$persons = PersonQuery::create()->find(); 
$personsById = $persons->getArrayCopy('Id'); 

然後,你可以做

$person = $personsById[3]; 

if (isset($personsById[3])) { 
    $person = $personsById[3]; 
    ... 
}