<!--
-File $Id: FindingObjects.html,v 1.3 2005/02/12 13:05:55 micha Exp $
-License GNU FDL (http://www.gnu.org/copyleft/fdl.html)
-Copyright 2003, Propel project
-Author Hans Lellelid, hide@address.com
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Propel Guide</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<link rel="Stylesheet" rev="Stylesheet" href="../css/Documentation.css" type="text/css" charset="iso-8859-1"/>
</head>
<body>
<h1>Finding Persisted Objects</h1>
<p>Una vez sus objetos han sido almacenados en la base de datos, usted necesitará una forma de traerlos de vuelta afuera.
usted ya a visto un breve ejemplo de cómo encontrar objetos usando criterios de criterio de propel. En este
capitulo revisaremos otros métodos de recuperación de objetos y examinaremos el sistema Criterio
en más detalle.</p>
<h2><a name="FindingRecords.byPK"></a>Tomando un registro específico</h2>
<p>Puede encontrar un registro específco (registro) usando el método <strong>retrieveByPK()</strong> de la clase Peer.
Como el nombre lo implica, este método buscara un registro especifico basado en la llave primaria
simple o compuesta provista.</p>
<pre title="retrieveByPk() simple key">
// The book table has a single primary key column: book_id
// Assuming that War & Peace was first book added to the table:
$warAndPeace = BookPeer::retrieveByPK(1);
</pre>
<p>Desde luego, en algunos casos usted puede tener una tabla en donde la llave primaria este actualmente definida por
los valores de varias columnas. Tomemos por ejemplo, la siguiente tabla de referencia para relaciones de muchos-a-muchos :</p>
<pre title="xref schema">
<table name="book_author_xref"
description="Book-Author Crossreference Table">
<column
name="book_id"
required="true"
primaryKey="true"
type="INTEGER"
description="Book Id"/>
<column
name="author_id"
required="true"
primaryKey="true"
type="INTEGER"
description="Author Id"/>
</table>
</pre>
<p>En este caso, recuperando una referencia específica(claramente un ejercicio menos útil), será terminado
pasando un arreglo al método <strong>retreiveByPK()</strong>. <strong>Note que el orden de las llaves es crítico
y debe corresponder a el orden en que las columnas fueron definidas en el archivo XML.</strong></p>
<pre title="retriveByPK() composite">
// Gets the book_id=1,author_id=2 record
$obj = BookAuthorXrefPeer::retrieveByPK(array(1,2));
</pre>
<h2><a name="FindingRecods.Criteria"></a>Seleccionar usando criterios</h2>
<p><strong>Nota: </strong>Algunas de las ideas y ejemplos para esta sección vienen
del dosumento <em>Criteria HOWTO</em> en la página web de <a href="Bibliography.html#bib.torque">Torque</a> .</p>
<p>Para encontrar registros conocidos usando criterios específicos, usted usará el objeto Criterio
en conjunto con el método <strong>doSelect()</strong> de la clase peer. Este es un muy
poderoso significado de locación de criterios, como puede construirlo en la casi cualquier consulta SQL
usando el sistema de Criterio. El método <strong>doSelect()</strong>
retornará un arreglo de objetos del tipo apropiado.</p>
<pre title="doSelect() example">$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Leo");
$results = AuthorPeer::doSelect($c);
foreach($results as $author) {
print "Author: " . $author->getLastName() . ", " . $author->getFirstName() . "\n";
} </pre>
<p>Tomar los resultados sellecionados es fácil, y se encontrará que con un poco de práctica
representar aún una consulta muy complicada es simple usando la aproximación por Criterios .</p>
<h3>Criterio simple</h3>
<p> En la forma más simple, el sistema de criterios es donde usted controla las condiciones
para seleccionar registros:</p>
<pre title="Criteria: simple">
$c = new Criteria();
// Find all authors with first name Karl but
// last name is _not_ Marx.
$c->add(AuthorPeer::FIRST_NAME, "Karl");
$c->add(AuthorPeer::LAST_NAME, "Marx", Criteria::NOT_EQUAL);
// Find all authors with last name of Tolstoy, Dostoevsky, or Bakhtin
$c2 = new Criteria();
$c2->add(AuthorPeer::LAST_NAME, array("Tolstoy", "Dostoevsky", "Bakhtin"), Criteria::IN);
</pre>
<h3>Criterios combinados</h3>
<p>Usted no puede combinar objetos criterios directamente, pewro puede combinar objetos criterio en orden de
especificar relaciones lógocas entre clausulas.</p>
<pre title="Criteria: combining">
// Find all authors with first name "Leo" OR last name of
// "Tolstoy", "Dostoevsky", or "Bakhtin"
$c = new Criteria();
$cton1 = $c->getNewCriterion(AuthorPeer::FIRST_NAME, "Leo");
$cton2 = $c->getNewCriterion(AuthorPeer::LAST_NAME,
array("Tolstoy", "Dostoevsky", "Bakhtin"), Criteria::IN);
// combine them
$cton1->addOr($cton2);
// add to Criteria
$c->add($cton1);
</pre>
<h3>Specificando Multiples Condiciones para una Columna</h3>
<p>En el ejemplo anterior vimos como especificar condiciones simples para una columna (ej. author.FIRST_NAME = "Leo").
Importantemente, especificando multiples condiciones para una columna sencilla, es más complicado porque Propel almacena
criterios en una tabla hash (por razones de rendimiento).</p>
<p><strong>Esto está MAL:</strong></p>
<pre title="Criteria: WRONG use of multiple conditions">
$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Leo%", Criteria::LIKE);
$c->add(AuthorPeer::FIRST_NAME, "Leonardo", Criteria::NOT_EQUAL);
// second add() just overwrote the LIKE condition already in place!
</pre>
<p>La forma correcta de hacer esto involucra crear<em>Criterion</em> objetos y usar el método
<strong>Criterion::addOr()</strong> para contar con ellos:</p>
<pre title="Criteria: CORRECT use of multiple conditions">
$c = new Criteria();
$criterion = $c->getNewCriterion(AuthorPeer::FIRST_NAME, "Leo%", Criteria::LIKE);
$criterion->addOr($c->getNewCriterion(AuthorPeer::FIRST_NAME, "Leonardo", Criteria::NOT_EQUAL));
$c->add($criterion);
</pre>
<h3>Controlando otros Aspectos de la consulta</h3>
<p>El objeto criterio puede hacer más que simplemente controlar las condiciones expresadas en la consulta SQL. El otro
aspecto de la consulta que puede ser controlada incluye: el número de registros retornado, caso-sensitio, y
el orden de los registros.</p>
<pre title="">
// find first 10 authors, alphabetically
$c = new Criteria();
$c->setLimit(10);
$c->addAscendingOrderByColumn(AuthorPeer::LAST_NAME);
// find all authors named "max", case-insensitive
$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "max");
$c->setIgnoreCase(true);
</pre>
<p><strong>Nota: </strong>Algunas bases de datos soportan limitar las consultas en SQL (ej. MySQL y PostgreSQL soportan
el keyword LIMIT); en esos casos la clase BasePeer usara la limitación nativa, mientras que en otros casos
emulando el límite soportado(trayendo el recordset completo pero solo adicionando limites específicos para resultar en un arreglo).</p>
<h3>Características avanzadas de criterios</h3>
<p>El objeto criterio puede ser manejado alguna vez si desea escribir código que retorne resultados de consulta en columna
(mós que objetos instantaneos ). Por ejemplo, si necesita un código más eficiente que pueda
retornar una lista de todos los ISBNs en la base de datos, filtrados y especificados sobre un criterio específico:</p>
<pre title="Specyfing select columns in criteria">
class BookPeer extends BaseBookPeer {
.
.
.
/**
* Get just the ISBN numbers for books.
* @param Criteria $c Criteria to filter results.
* @return array Array of ISBN numbers.
*/
function getJustISBN(Criteria $c) {
$c->clearSelectColumns()->addSelectColumn(self::ISBN);
$rs = BasePeer::doSelectRS($c);
$isbns = array();
while($rs->next()) {
$isbns[] = $rs->get(1);
}
return $isbns;
}
</pre>
<h2><a name="WritingSQL"></a>Seleccionar usando SQL</h2>
<p>La clase criterio está disponible para construir comodamente consultas usadas, pero esto no
pretende ser capaz de construir una consulta. En casos donde necesita rendimiento
particularmente en consultas complejas necesitara escribir sus propios estamentos SQL.
La forma recomendada para hacer esto es usando sus clases stub. Para estar seguro de que
su consulta no va a fallar si las columnas de una tabla son renombradas usted puede usar las constantes
Peer::COLUMN_NAME y Peer::TABLENAME .</p>
<pre title="Writing SQL example">
class BookPeer extends BaseBookPeer {
.
.
.
/**
* Get just the Books that have not been reviewed.
* @return array Book[]
*/
function getUnreviewedBooks() {
$con = Propel::getConnection(DATABASE_NAME);
// if not using a driver that supports sub-selects
// you must do a cross join (left join w/ NULL)
$sql = "SELECT books.* FROM books WHERE ".
"NOT EXISTS (SELECT id FROM review WHERE book_id = book.id)";
$stmt = $con->createStatement();
$rs = $stmt->executeQuery($sql, ResultSet::FETCHMODE_NUM);
return parent::populateObjects($rs);
}</pre>
<p><em>Nota: En el ejemplo anterior es asumido que la columna en su tabla fué
definida en el mismo orden como en el esquema de colimnas del archivo XML. Esto sera generalmente
en el caso que no haya modificado la tabla. Usted puede usar los criteriose <strong>Peer::addSelectColumns</strong>
y<strong> Criteria->getSelectColumns()</strong> para quitar esta dependencia.</em></p>
<p>En nuestro ejemplo no usamos las columnas constantes (para mantenerlo simple), pero
usted puede facilmente hacerlo en SQL para evitasr la necesidad de cambiar su SQL
si cambia la columna o nombre de la tabla:</p>
<pre title="SQL example using constants">$sql = "SELECT b.* FROM ".BookPeer::TABLE_NAME." b WHERE ".
"NOT EXISTS (SELECT r.".ReviewPeer::ID." FROM ".ReviewPeer::TABLE_NAME." r ".
" WHERE r.".ReviewPeer::BOOK_ID." = b.".BookPeer::ID.")";</pre>
<p>Es ciertamente su desición si la flexibilidad de SQL sobre el valor
adicional de los retos de legibilidad que introduce.</p>
<h2><a name="PopulatingSingleObjects"></a>Trayendo grandes juegos de resultados</h2>
<p>En algunos casos no querra Peer para poblar todos los objetos y retornarlos
en un arreglo. Particularmente, cuando se traen grandes resultados en PHP se puede correr
el riesgo de falta de memoria si pregunta para retornar un arreglo de objetos hidratados. Tomarlo alrededor
de esta emisión,puede interar a travées del juego de resultados y poblar objetos simples
usando el método <strong>Entity->hydrate() </strong>, disponiendo de ellos cuando
usted ha terminado.</p>
<pre title="populate single object">// fetch entire list of books (we'll pretend this is huge)
$rs = BookPeer::doSelectRS(new Criteria());
while($rs->next()) { // use Creole ResultSet methods to iterate over resultset
$book = new Book();
$book->hydrate($rs);
// read $book values, save $book, etc.
...
}</pre>
<p>Desde luego este trabajo si usa criterio de rendimiento SELECT (como un ejemplo)
o usar los de SQL. Algo importante que notar es que el resultado es sólo
retribuido desde la base de datos en el objeto hidratado cuando sea necesario.</p>
</body>
</html>