2012-09-03 23 views
8

Używam Propel 1.6 i nie jestem pewien, jak uzyskać obiekt (biorąc pod uwagę jego "id" wartość atrybutu) z kolekcji obiektu propel. Nie mogłem znaleźć prostej odpowiedzi w dokumentacji Propela (PropelCollection methods) nie wydaje się mieć zastosowania?). Na przykład: Powiedzmy mam „osoba” stół z następującym schematem:Jak zdobyć obiekt przez "id" z kolekcji obiektów propagandowych?

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

zrobić następujące kwerendy, aby uzyskać kolekcji obiektów „osoba”:

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

Potem chcesz znaleźć obiekt "Person" z podanym "id" (np. "Person" z "id = 3"), bez dodawania nowego zapytania do bazy danych. Jak mogę to zrobić?

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

Innymi słowy, nie chcę zrobić:

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

kontekstu:

chciałbym uniknąć tworzenia zapytania do bazy danych w celu zwiększenia wydajności. Oświadczenie ma być wprowadzony wewnątrz foreach, które w przeciwnym razie prowadziłoby do licznych połączeń z bazą danych, jak następuje:

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

Odpowiedz

4

Dobrze, że nie będzie bardzo wydajny, ale można przejść przez kolekcję, aby ją znaleźć .

$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

Można to zrobić w bardziej elegancki sposób z 'array_filter()' :-) – Florent

+0

@ J0K: Starałam aby uniknąć pętli foreach, ale jak sądzę, nie mogę tego uniknąć. Myślę, że przejście z pętlą nadal byłoby bardziej wydajne niż wykonywanie wielu połączeń z bazą danych. Dzięki za odpowiedź! – RayOnAir

+1

@Florent: Nie jestem pewien, jak zaimplementować funkcję [array_filter] (http://php.net/manual/en/function.array-filter.php) w ​​tym przypadku, ale zbadam ... dzięki! – RayOnAir

3

Od Propel nie buforują prawidłowo kwerendy wynik, trzeba iteracyjne kolekcji (jak @ J0K powiedział). Zamiast używać pętli foreach można wywołać array_filter przekazując zamknięcie (z 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]; 

Jeżeli jesteś pewien, że dana osoba zostanie znaleziony, można również napisać (z PHP 5.4) następujące wiersze:

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

dzięki za udostępnienie alternatywnego rozwiązania przy użyciu array_filter! Czy to rozwiązanie byłoby lepsze z punktu widzenia wydajności, w porównaniu do korzystania z pętli foreach? Jeśli tak, czy mógłbyś dzielić się intuicją? – RayOnAir

+1

W PHP 5.4, 'foreach' jest 3x szybszy niż' array_filter() '. Ponadto używając 'foreach' możesz' break' po znalezieniu twojego wpisu. Ale moim zdaniem 'array_filter()' jest bardziej estetyczny. – Florent

+0

Będę o tym pamiętać. dzięki! – RayOnAir

2

jeśli ustawisz Propel :: isInstancePoolingEnabled() jest prawdziwe (domyślnie jest to prawdą), następnie możesz przepraszać za mój angielski.

7

Inną alternatywą, zwłaszcza jeśli trzeba szukać kilka razy jest dostać tablicę obiektów przez id z $ Collection-> getArrayCopy ('id').

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

Następnie można zrobić

$person = $personsById[3]; 

lub

if (isset($personsById[3])) { 
    $person = $personsById[3]; 
    ... 
} 
Powiązane problemy