2012-09-03 10 views
8

Estoy usando Propel 1.6 y no estoy seguro de cómo obtener un objeto (dado su valor de atributo "id") de una colección de objetos de propel. No pude encontrar una respuesta directa en la documentación de Propel (PropelCollection methods no parece aplicable?). Por ejemplo: Digamos que tengo una tabla de "persona" con el siguiente esquema:Cómo obtener el objeto por "id" desde la colección de objetos de propel?

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

hago la siguiente consulta para obtener una colección de objetos "persona":

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

Entonces, desea encontrar un objeto "Persona" con un "id" dado (por ejemplo, "Persona" con "id = 3"), sin hacer una nueva consulta a la base de datos. ¿Cómo puedo hacerlo?

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

En otras palabras, NO quiero hacer:

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

Contexto:

me gustaría evitar hacer una consulta de base de datos para mejorar el rendimiento. La declaración debe ser insertado dentro de una instrucción foreach que de otro modo dar lugar a numerosas conexiones de bases de datos, como la siguiente:

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

Respuesta

4

Bueno, eso no va a ser muy eficiente, pero se puede ir a través de la colección de encontrarlo .

$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

Puede hacerlo de una forma más elegante con 'array_filter()' :-) – Florent

+0

@ J0K: yo estaba tratando para evitar un ciclo foreach, pero supongo que, como sugieres, no puedo evitarlo. Creo que seguir con el bucle sería aún más eficiente que hacer conexiones de bases de datos múltiples. ¡Gracias por tu respuesta! – RayOnAir

+1

@ Florent: no estoy seguro de cómo implementar la función [array_filter] (http://php.net/manual/en/function.array-filter.php) en este caso, pero investigaré ... ¡Gracias! – RayOnAir

3

Desde Propel no conservan adecuadamente Resultado de la consulta, es necesario recorrer la colección (como @ J0K dijo). En lugar de usar un bucle foreach, puede llamar al array_filter pasando un cierre (con 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]; 

Si está seguro de que la persona se encuentre, también puede escribir (con PHP 5.4) las siguientes líneas:

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

¡gracias por compartir una solución alternativa usando array_filter! ¿Esta solución sería mejor desde el punto de vista del rendimiento, en comparación con el uso de un ciclo foreach? Si es así, ¿podría compartir la intuición detrás? – RayOnAir

+1

Con PHP 5.4, 'foreach' es 3 veces más rápido que' array_filter() '. Además, si usas 'foreach' puedes' romper' cuando encuentres tu entrada. Pero en mi opinión 'array_filter()' es más _aesthetic_. – Florent

+0

Lo tendré en cuenta. ¡Gracias! – RayOnAir

2

si establece Propel :: isInstancePoolingEnabled() es verdadera (es cierto por defecto), entonces usted puede

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

lo siento acerca de mi inglés.

7

Otra alternativa, especialmente si tiene que buscar en varias ocasiones es conseguir matriz de objetos por id con $ colección-> getArrayCopy ('Id').

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

A continuación, puede hacer

$person = $personsById[3]; 

o

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