Cuando ejecuta una consulta contra una clase Table usando los métodos find() o
fetchAll(), el resultado se devuelve en un objeto de tipo
Zend_Db_Table_Rowset_Abstract. Un Rowset contiene una colección de
objetos que descienden de Zend_Db_Table_Row_Abstract. Puede
iterar a través del Rowset y acceder a objetos Row individuales, leyendo o modificando datos
en las Rows.
Zend_Db_Table_Abstract proporciona los métodos
find() y fetchAll(), cada uno de los cuales
devuelve un objeto de tipo Zend_Db_Table_Rowset_Abstract.
Ejemplo 27.134. Ejemplo de obtención de un rowset
$bugs = new Bugs();
$rowset = $bugs->fetchAll("bug_status = 'NEW'");
El Rowset en sí es normalmente menos interesante que las Rows que contiene. Esta sección ilustra cómo obtener las Rows que componen el Rowset.
Una consulta legítima devuelve cero filas cuando ninguna fila de la base de datos coincide con las
condiciones de la consulta. Por lo tanto, un objeto Rowset podría contener cero objetos Row. Dado que
Zend_Db_Table_Rowset_Abstract implementa la interfaz
Countable, puede usar count()
para determinar el número de Rows en el Rowset.
Ejemplo 27.135. Contar las Rows en un Rowset
$rowset = $bugs->fetchAll("bug_status = 'FIXED'");
$rowCount = count($rowset);
if ($rowCount > 0) {
echo "found $rowCount rows";
} else {
echo 'no rows matched the query';
}
Ejemplo 27.136. Leer una única Row de un Rowset
La forma más simple de acceder a una Row de un Rowset es usar el
método current(). Esto es particularmente apropiado cuando el
Rowset contiene exactamente una Row.
$bugs = new Bugs();
$rowset = $bugs->fetchAll("bug_id = 1");
$row = $rowset->current();
Si el Rowset contiene cero filas, current() devuelve
el valor NULL de PHP.
Ejemplo 27.137. Iterar a través de un Rowset
Los objetos que descienden de Zend_Db_Table_Rowset_Abstract
implementan la interfaz SeekableIterator, lo que significa que puede
recorrerlos usando la construcción foreach(). Cada valor
que recupera de esta manera es un objeto Zend_Db_Table_Row_Abstract
que corresponde a un registro de la tabla.
$bugs = new Bugs();
// fetch all records from the table
$rowset = $bugs->fetchAll();
foreach ($rowset as $row) {
// output 'Zend_Db_Table_Row' or similar
echo get_class($row) . "\n";
// read a column in the row
$status = $row->bug_status;
// modify a column in the current row
$row->assigned_to = 'mmouse';
// write the change to the database
$row->save();
}
Ejemplo 27.138. Desplazarse a una posición conocida dentro de un Rowset
SeekableIterator le permite desplazarse a una posición a la
que le gustaría que el iterador salte. Simplemente use el método seek()
para eso. Páselo un entero que represente el número de la Row a la que
le gustaría que su Rowset apunte a continuación; no olvide que empieza con el índice 0. Si el
índice es incorrecto, es decir, no existe, se lanzará una excepción. Debe usar
count() para comprobar el número de resultados antes de desplazarse a una
posición.
$bugs = new Bugs(); // fetch all records from the table $rowset = $bugs->fetchAll(); // takes the iterator to the 9th element (zero is one element) : $rowset->seek(8); // retrieve it $row9 = $rowset->current(); // and use it $row9->assigned_to = 'mmouse'; $row9->save();
getRow() le permite obtener una Row específica en el Rowset,
conociendo su posición; no olvide, sin embargo, que las posiciones empiezan con el índice cero. El
primer parámetro de getRow() es un entero para la posición
solicitada. El segundo parámetro opcional es un booleano; indica al iterador del Rowset si
debe desplazarse a esa posición al mismo tiempo o no (el valor predeterminado es
FALSE). Este método devuelve un objeto
Zend_Db_Table_Row por defecto. Si la
posición solicitada no existe, se lanzará una excepción. He aquí un ejemplo:
$bugs = new Bugs(); // fetch all records from the table $rowset = $bugs->fetchAll(); // retrieve the 9th element immediately: $row9 = $rowset->getRow(8); // and use it: $row9->assigned_to = 'mmouse'; $row9->save();
Después de tener acceso a un objeto Row individual, puede manipular la Row usando los métodos descritos en Zend_Db_Table_Row.
Puede acceder a todos los datos del Rowset como un array usando el
método toArray() del objeto Rowset. Esto devuelve un array
que contiene una entrada por Row. Cada entrada es un array asociativo con claves que
corresponden a nombres de columna y elementos que corresponden a los respectivos valores de columna.
Ejemplo 27.139. Uso de toArray()
$bugs = new Bugs();
$rowset = $bugs->fetchAll();
$rowsetArray = $rowset->toArray();
$rowCount = 1;
foreach ($rowsetArray as $rowArray) {
echo "row #$rowCount:\n";
foreach ($rowArray as $column => $value) {
echo "\t$column => $value\n";
}
++$rowCount;
echo "\n";
}
El array devuelto por toArray() no es actualizable. Es decir,
puede modificar valores en el array como con cualquier array, pero los cambios en los datos
del array no se propagan a la base de datos.
Los objetos de tipo Zend_Db_Table_Rowset_Abstract son serializables.
De manera similar a serializar un objeto Row individual, puede serializar un Rowset
y deserializarlo más tarde.
Ejemplo 27.140. Serializar un Rowset
Simplemente use la función serialize() de PHP para
crear una cadena que contenga una representación en flujo de bytes del argumento
objeto Rowset.
$bugs = new Bugs(); $rowset = $bugs->fetchAll(); // Convert object to serialized form $serializedRowset = serialize($rowset); // Now you can write $serializedRowset to a file, etc.
Ejemplo 27.141. Deserializar un Rowset serializado
Use la función unserialize() de PHP para
restaurar una cadena que contenga una representación en flujo de bytes de un objeto. La función
devuelve el objeto original.
Tenga en cuenta que el objeto Rowset devuelto está en un estado desconectado. Puede iterar a través del Rowset y leer los objetos Row y sus propiedades, pero no puede cambiar valores en las Rows ni ejecutar otros métodos que requieran una conexión a la base de datos (por ejemplo, consultas contra tablas relacionadas).
$rowsetDisconnected = unserialize($serializedRowset); // Now you can use object methods and properties, but read-only $row = $rowsetDisconnected->current(); echo $row->bug_description;
![]() |
¿Por qué los Rowsets se deserializan en un estado desconectado? |
|---|---|
Un objeto serializado es una cadena que puede leer cualquiera que la posea. Podría ser un riesgo de seguridad almacenar parámetros como la cuenta y la contraseña de la base de datos en texto plano sin cifrar dentro de la cadena serializada. No querría almacenar dichos datos en un archivo de texto que no esté protegido, ni enviarlos por correo electrónico u otro medio que sea fácilmente legible por posibles atacantes. Quien lea el objeto serializado no debería poder usarlo para obtener acceso a su base de datos sin conocer credenciales válidas. |
Puede reactivar un Rowset desconectado usando el método setTable().
El argumento de este método es un objeto válido de tipo
Zend_Db_Table_Abstract, que usted crea. Crear un objeto Table
requiere una conexión activa a la base de datos, por lo que, al reasociar la Table con el
Rowset, el Rowset obtiene acceso a la base de datos. Posteriormente, puede cambiar valores en
los objetos Row contenidos en el Rowset y guardar los cambios en la base de datos.
Ejemplo 27.142. Reactivar un Rowset como datos activos
$rowset = unserialize($serializedRowset); $bugs = new Bugs(); // Reconnect the rowset to a table, and // thus to a live database connection $rowset->setTable($bugs); $row = $rowset->current(); // Now you can make changes to the row and save them $row->bug_status = 'FIXED'; $row->save();
Reactivar un Rowset con setTable() también reactiva todos los
objetos Row contenidos en ese Rowset.
Puede usar una clase concreta alternativa para instancias de Rowsets
extendiendo Zend_Db_Table_Rowset_Abstract. Especifique la clase
Rowset personalizada por nombre, ya sea en el miembro protegido
$_rowsetClass de una clase Table, o en el argumento de array del
constructor de un objeto Table.
Ejemplo 27.143. Especificar una clase Rowset personalizada
class MyRowset extends Zend_Db_Table_Rowset_Abstract
{
// ...customizations
}
// Specify a custom Rowset to be used by default
// in all instances of a Table class.
class Products extends Zend_Db_Table_Abstract
{
protected $_name = 'products';
protected $_rowsetClass = 'MyRowset';
}
// Or specify a custom Rowset to be used in one
// instance of a Table class.
$bugs = new Bugs(array('rowsetClass' => 'MyRowset'));
Normalmente, la clase concreta estándar Zend_Db_Rowset es
suficiente para la mayoría de los usos. Sin embargo, podría resultarle útil
añadir nueva lógica a un Rowset, específica para una Table dada.
Por ejemplo, un nuevo método podría calcular un agregado
sobre todas las Rows en el Rowset.
Ejemplo 27.144. Ejemplo de clase Rowset con un nuevo método
class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
{
/**
* Find the Row in the current Rowset with the
* greatest value in its 'updated_at' column.
*/
public function getLatestUpdatedRow()
{
$max_updated_at = 0;
$latestRow = null;
foreach ($this as $row) {
if ($row->updated_at > $max_updated_at) {
$latestRow = $row;
}
}
return $latestRow;
}
}
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
protected $_rowsetClass = 'MyBugsRowset';
}
![[Note]](images/note.png)