TigerZF
🌐Español

27.6. Zend_Db_Table_Row

27.6.1. Introducción

Zend_Db_Table_Row es una clase que contiene una fila individual de un objeto Zend_Db_Table. Cuando se ejecuta una consulta contra una clase Table, el resultado se devuelve en un conjunto de objetos Zend_Db_Table_Row. También puede usar este objeto para crear nuevas filas y añadirlas a la tabla de la base de datos.

Zend_Db_Table_Row es una implementación del patrón Row Data Gateway.

27.6.2. Obteniendo una fila

Zend_Db_Table_Abstract proporciona los métodos find() y fetchAll(), que cada uno devuelve un objeto de tipo Zend_Db_Table_Rowset, y el método fetchRow(), que devuelve un objeto de tipo Zend_Db_Table_Row.

Ejemplo 27.117. Ejemplo de obtención de una fila

$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

Un objeto Zend_Db_Table_Rowset contiene una colección de objetos Zend_Db_Table_Row. Consulte el capítulo sobre table rowset para más detalles.

Ejemplo 27.118. Ejemplo de lectura de una fila en un rowset

$bugs = new Bugs();
$rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
$row = $rowset->current();

27.6.2.1. Lectura de valores de columna desde una fila

Zend_Db_Table_Row_Abstract proporciona métodos de acceso para que pueda referenciar las columnas de la fila como propiedades del objeto.

Ejemplo 27.119. Ejemplo de lectura de una columna en una fila

$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

// Echo the value of the bug_description column
echo $row->bug_description;

[Note] Nota

Versiones anteriores de Zend_Db_Table_Row mapeaban estos accesores de columna a los nombres de las columnas de la base de datos mediante una transformación de cadenas denominada inflexión.

Actualmente, Zend_Db_Table_Row no implementa la inflexión. Los nombres de las propiedades a las que se accede deben coincidir con la escritura de los nombres de las columnas tal como aparecen en su base de datos.

27.6.2.2. Recuperando los datos de la fila como un array

Puede acceder a los datos de la fila como un array usando el método toArray() del objeto Row. Esto devuelve un array asociativo de los nombres de las columnas a los valores de las columnas.

Ejemplo 27.120. Ejemplo del uso del método toArray()

$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

// Get the column/value associative array from the Row object
$rowArray = $row->toArray();

// Now use it as a normal array
foreach ($rowArray as $column => $value) {
    echo "Column: $column\n";
    echo "Value:  $value\n";
}

El array devuelto por toArray() no es actualizable. Puede modificar los valores del array como con cualquier array, pero no puede guardar los cambios de este array en la base de datos directamente.

27.6.2.3. Obtención de datos de tablas relacionadas

La clase Zend_Db_Table_Row_Abstract proporciona métodos para obtener filas y rowsets de tablas relacionadas. Consulte el capítulo de relaciones para más información sobre las relaciones entre tablas.

27.6.3. Escribiendo filas en la base de datos

27.6.3.1. Cambiando valores de columna en una fila

Puede establecer valores de columna individuales usando los accesores de columna, de forma similar a cómo se leen las columnas como propiedades del objeto en el ejemplo anterior.

Usar un accesor de columna para establecer un valor cambia el valor de la columna del objeto fila en su aplicación, pero no confirma el cambio en la base de datos todavía. Puede hacerlo con el método save().

Ejemplo 27.121. Ejemplo de cambio de una columna en una fila

$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

// Change the value of one or more columns
$row->bug_status = 'FIXED';

// UPDATE the row in the database with new values
$row->save();

27.6.3.2. Insertando una nueva fila

Puede crear una nueva fila para una tabla dada con el método createRow() de la clase Table. Puede acceder a los campos de esta fila con la interfaz orientada a objetos, pero la fila no se almacena en la base de datos hasta que llame al método save().

Ejemplo 27.122. Ejemplo de creación de una nueva fila para una tabla

$bugs = new Bugs();
$newRow = $bugs->createRow();

// Set column values as appropriate for your application
$newRow->bug_description = '...description...';
$newRow->bug_status = 'NEW';

// INSERT the new row to the database
$newRow->save();

El argumento opcional del método createRow() es un array asociativo, con el que puede rellenar los campos de la nueva fila.

Ejemplo 27.123. Ejemplo de rellenado de una nueva fila para una tabla

$data = array(
    'bug_description' => '...description...',
    'bug_status'      => 'NEW'
);

$bugs = new Bugs();
$newRow = $bugs->createRow($data);

// INSERT the new row to the database
$newRow->save();

[Note] Nota

El método createRow() se llamaba fetchNew() en versiones anteriores de Zend_Db_Table. Se recomienda usar el nuevo nombre de método, aunque el nombre antiguo sigue funcionando por motivos de compatibilidad con versiones anteriores.

27.6.3.3. Cambiando valores en varias columnas

Zend_Db_Table_Row_Abstract proporciona el método setFromArray() para permitirle establecer varias columnas en una sola fila a la vez, especificadas en un array asociativo que asigna los nombres de columna a los valores. Puede encontrar este método conveniente para establecer valores tanto para filas nuevas como para filas que necesite actualizar.

Ejemplo 27.124. Ejemplo del uso de setFromArray() para establecer valores en una nueva fila

$bugs = new Bugs();
$newRow = $bugs->createRow();

// Data are arranged in an associative array
$data = array(
    'bug_description' => '...description...',
    'bug_status'      => 'NEW'
);

// Set all the column values at once
$newRow->setFromArray($data);

// INSERT the new row to the database
$newRow->save();

27.6.3.4. Eliminando una fila

Puede llamar al método delete() en un objeto Row. Esto elimina las filas en la base de datos que coinciden con la clave primaria del objeto Row.

Ejemplo 27.125. Ejemplo de eliminación de una fila

$bugs = new Bugs();
$row = $bugs->fetchRow('bug_id = 1');

// DELETE this row
$row->delete();

No es necesario llamar a save() para aplicar la eliminación; se ejecuta contra la base de datos inmediatamente.

27.6.4. Serializando y deserializando filas

A menudo resulta conveniente guardar el contenido de una fila de la base de datos para usarlo más adelante. Serialización es el nombre de la operación que convierte un objeto en una forma fácil de guardar en almacenamiento fuera de línea (por ejemplo, un archivo). Los objetos de tipo Zend_Db_Table_Row_Abstract son serializables.

27.6.4.1. Serializando una fila

Simplemente use la función serialize() de PHP para crear una cadena que contenga una representación en secuencia de bytes del objeto Row.

Ejemplo 27.126. Ejemplo de serialización de una fila

$bugs = new Bugs();
$row = $bugs->fetchRow('bug_id = 1');

// Convert object to serialized form
$serializedRow = serialize($row);

// Now you can write $serializedRow to a file, etc.

27.6.4.2. Deserializando datos de fila

Use la función unserialize() de PHP para restaurar una cadena que contenga una representación en secuencia de bytes de un objeto. La función devuelve el objeto original.

Tenga en cuenta que el objeto Row devuelto está en un estado desconectado. Puede leer el objeto Row y sus propiedades, pero no puede cambiar valores en la fila ni ejecutar otros métodos que requieran una conexión a la base de datos (por ejemplo, consultas contra tablas relacionadas).

Ejemplo 27.127. Ejemplo de deserialización de una fila serializada

$rowClone = unserialize($serializedRow);

// Now you can use object properties, but read-only
echo $rowClone->bug_description;

[Note] ¿Por qué las filas se deserializan en un estado desconectado?

Un objeto serializado es una cadena que es legible por cualquiera que la posea. Podría ser un riesgo de seguridad almacenar parámetros como la cuenta de la base de datos y la contraseña en texto plano sin cifrar dentro de la cadena serializada. No querría almacenar tales datos en un archivo de texto que no esté protegido, ni enviarlos en un correo electrónico u otro medio fácilmente legible por posibles atacantes. El lector de el objeto serializado no debería poder usarlo para obtener acceso a su base de datos sin conocer credenciales válidas.

27.6.4.3. Reactivando una fila como datos activos

Puede reactivar una fila desconectada 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, de modo que al reasociar la Table con la Row, la Row obtiene acceso a la base de datos. Posteriormente, puede cambiar los valores del objeto Row y guardar los cambios en la base de datos.

Ejemplo 27.128. Ejemplo de reactivación de una fila

$rowClone = unserialize($serializedRow);

$bugs = new Bugs();

// Reconnect the row to a table, and
// thus to a live database connection
$rowClone->setTable($bugs);

// Now you can make changes to the row and save them
$rowClone->bug_status = 'FIXED';
$rowClone->save();

27.6.5. Extendiendo la clase Row

Zend_Db_Table_Row es la clase concreta predeterminada que extiende Zend_Db_Table_Row_Abstract. Puede definir su propia clase concreta para instancias de Row extendiendo Zend_Db_Table_Row_Abstract. Para usar su nueva clase Row para almacenar resultados de las consultas de Table, especifique la clase Row personalizada por su nombre ya sea en el miembro protegido $_rowClass de una clase Table, o en el array del argumento del constructor de un objeto Table.

Ejemplo 27.129. Especificación de una clase Row personalizada

class MyRow extends Zend_Db_Table_Row_Abstract
{
    // ...customizations
}

// Specify a custom Row to be used by default
// in all instances of a Table class.
class Products extends Zend_Db_Table_Abstract
{
    protected $_name = 'products';
    protected $_rowClass = 'MyRow';
}

// Or specify a custom Row to be used in one
// instance of a Table class.
$bugs = new Bugs(array('rowClass' => 'MyRow'));

27.6.5.1. Inicialización de la fila

Si se necesita inicializar lógica específica de la aplicación cuando se construye una fila, puede optar por trasladar sus tareas al método init(), que se llama después de que se hayan procesado todos los metadatos de la fila. Esto se recomienda por encima del método __construct() si no necesita alterar los metadatos de forma programática.

Ejemplo 27.130. Ejemplo de uso del método init()

class MyApplicationRow extends Zend_Db_Table_Row_Abstract
{
    protected $_role;

    public function init()
    {
        $this->_role = new MyRoleClass();
    }
}

27.6.5.2. Definiendo lógica personalizada para Insert, Update y Delete en Zend_Db_Table_Row

La clase Row llama a los métodos protegidos _insert(), _update(), y _delete() antes de realizar las operaciones correspondientes INSERT, UPDATE, y DELETE. Puede añadir lógica a estos métodos en su subclase Row personalizada.

Si necesita hacer lógica personalizada en una tabla específica, y la lógica personalizada debe ocurrir en cada operación sobre esa tabla, puede tener más sentido implementar su código personalizado en los métodos insert(), update() y delete() de su clase Table. Sin embargo, a veces puede ser necesario realizar lógica personalizada en la clase Row.

A continuación se muestran algunos casos de ejemplo en los que podría tener sentido implementar lógica personalizada en una clase Row en lugar de en la clase Table:

Ejemplo 27.131. Ejemplo de lógica personalizada en una clase Row

La lógica personalizada puede no aplicarse en todos los casos de operaciones sobre la Table respectiva. Puede proporcionar lógica personalizada bajo demanda implementándola en una clase Row y creando una instancia de la clase Table con esa clase Row personalizada especificada. De lo contrario, la Table usa la clase Row predeterminada.

Necesita que las operaciones de datos en esta tabla registren la operación en un objeto Zend_Log, pero solo si la configuración de la aplicación ha habilitado este comportamiento.

class MyLoggingRow extends Zend_Db_Table_Row_Abstract
{
    protected function _insert()
    {
        $log = Zend_Registry::get('database_log');
        $log->info(Zend_Debug::dump($this->_data,
                                    "INSERT: $this->_tableClass",
                                    false)
                  );
    }
}

// $loggingEnabled is an example property that depends
// on your application configuration
if ($loggingEnabled) {
    $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
} else {
    $bugs = new Bugs();
}

Ejemplo 27.132. Ejemplo de una clase Row que registra datos de inserción para varias tablas

La lógica personalizada puede ser común a varias tablas. En lugar de implementar la misma lógica personalizada en cada una de sus clases Table, puede implementar el código para dichas acciones en la definición de una clase Row, y usar esta Row en cada una de sus clases Table.

En este ejemplo, el código de registro es idéntico en todas las clases de tabla.

class MyLoggingRow extends Zend_Db_Table_Row_Abstract
{
    protected function _insert()
    {
        $log = Zend_Registry::get('database_log');
        $log->info(Zend_Debug::dump($this->_data,
                                    "INSERT: $this->_tableClass",
                                    false)
                  );
    }
}

class Bugs extends Zend_Db_Table_Abstract
{
    protected $_name = 'bugs';
    protected $_rowClass = 'MyLoggingRow';
}

class Products extends Zend_Db_Table_Abstract
{
    protected $_name = 'products';
    protected $_rowClass = 'MyLoggingRow';
}

27.6.5.3. Definir la inflexión en Zend_Db_Table_Row

Algunas personas prefieren que el nombre de la clase Table coincida con un nombre de tabla en el RDBMS mediante una transformación de cadenas denominada inflexión.

Las clases Zend_Db no implementan la inflexión de forma predeterminada. Consulte el capítulo sobre inflexión de extensión para una explicación de esta política.

Si prefiere usar la inflexión, debe implementar la transformación usted mismo, sobrescribiendo el método _transformColumn() en una clase Row personalizada, y usando esa clase Row personalizada cuando realice consultas contra su clase Table.

Ejemplo 27.133. Ejemplo de definición de una transformación de inflexión

Esto le permite usar una versión inflexionada del nombre de columna en los accesores. La clase Row usa el método _transformColumn() para cambiar el nombre que usa por el nombre nativo de la columna en la tabla de la base de datos.

class MyInflectedRow extends Zend_Db_Table_Row_Abstract
{
    protected function _transformColumn($columnName)
    {
        $nativeColumnName = myCustomInflector($columnName);
        return $nativeColumnName;
    }
}

class Bugs extends Zend_Db_Table_Abstract
{
    protected $_name = 'bugs';
    protected $_rowClass = 'MyInflectedRow';
}

$bugs = new Bugs();
$row = $bugs->fetchNew();

// Use camelcase column names, and rely on the
// transformation function to change it into the
// native representation.
$row->bugDescription = 'New description';

Usted es responsable de escribir las funciones para realizar la transformación de inflexión. Zend Framework no proporciona tal función.