La clase Zend_Db_Table es una interfaz orientada a objetos para
tablas de bases de datos. Proporciona métodos para muchas operaciones comunes sobre tablas. La clase
base es extensible, de modo que puede añadir lógica personalizada.
La solución Zend_Db_Table es una implementación del patrón
Table Data
Gateway. La solución también incluye una clase que implementa el patrón
Row Data
Gateway.
A partir de Zend Framework 1.9, puede instanciar Zend_Db_Table. Este
beneficio añadido significa que no tiene que extender una clase base y configurarla para realizar
operaciones simples tales como seleccionar, insertar, actualizar y eliminar en una única
tabla. A continuación se muestra un ejemplo del caso de uso más simple.
Ejemplo 27.80. Declarar una clase de tabla usando solo el nombre en forma de cadena
Zend_Db_Table::setDefaultAdapter($dbAdapter);
$bugTable = new Zend_Db_Table('bug');
El ejemplo anterior representa el caso de uso más simple. Tenga en cuenta todas las
opciones descritas más abajo para configurar tablas Zend_Db_Table. Si
quiere poder usar el caso de uso concreto, además de las funciones de relación más
complejas, consulte la documentación de Zend_Db_Table_Definition.
Para cada tabla de su base de datos a la que quiera acceder, defina una clase que extienda
Zend_Db_Table_Abstract.
Declare la tabla de la base de datos para la que se define esta clase, usando la
variable protegida $_name. Se trata de una cadena, y debe contener el
nombre de la tabla tal y como aparece escrito en la base de datos.
Ejemplo 27.81. Declarar una clase de tabla con nombre de tabla explícito
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
}
Si no especifica el nombre de la tabla, se usa por defecto el nombre de la clase. Si confía en este comportamiento por defecto, el nombre de la clase debe coincidir con el nombre de la tabla tal y como aparece en la base de datos.
Ejemplo 27.82. Declarar una clase de tabla con nombre de tabla implícito
class bugs extends Zend_Db_Table_Abstract
{
// el nombre de la tabla coincide con el nombre de la clase
}
También puede declarar el esquema de la tabla, ya sea con la variable protegida
$_schema, o con el esquema anteponiéndolo al nombre de la tabla en la
propiedad $_name. Cualquier esquema especificado con la propiedad
$_name tiene prioridad sobre un esquema especificado con la propiedad
$_schema. En algunas marcas de RDBMS, el
término para esquema es "base de datos" o "tablespace", pero se usa de forma similar.
Ejemplo 27.83. Declarar una clase de tabla con esquema
// Primera alternativa:
class Bugs extends Zend_Db_Table_Abstract
{
protected $_schema = 'bug_db';
protected $_name = 'bugs';
}
// Segunda alternativa:
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bug_db.bugs';
}
// Si se especifican esquemas tanto en $_name como en $_schema, el que
// se especifica en $_name tiene prioridad:
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bug_db.bugs';
protected $_schema = 'ignored';
}
El esquema y los nombres de tabla también se pueden especificar mediante directivas de
configuración del constructor, que sobrescriben cualquier valor por defecto especificado con
las propiedades $_name y $_schema. Una
especificación de esquema dada con la directiva name sobrescribe cualquier valor
proporcionado con la opción schema.
Ejemplo 27.84. Declarar los nombres de tabla y esquema al instanciar
class Bugs extends Zend_Db_Table_Abstract
{
}
// Primera alternativa:
$tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
// Segunda alternativa:
$tableBugs = new Bugs(array('name' => 'bug_db.bugs'));
// Si se especifican esquemas tanto en 'name' como en 'schema', el que
// se especifica en 'name' tiene prioridad:
$tableBugs = new Bugs(array('name' => 'bug_db.bugs',
'schema' => 'ignored'));
Si no especifica el nombre del esquema, se usa por defecto el esquema al que está conectada su instancia de adaptador de base de datos.
Toda tabla debe tener una clave primaria. Puede declarar la columna de la clave primaria
usando la variable protegida $_primary. Puede ser una cadena
que nombre la única columna para la clave primaria, o bien un array de nombres de
columnas si su clave primaria es compuesta.
Ejemplo 27.85. Ejemplo de especificación de la clave primaria
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
protected $_primary = 'bug_id';
}
Si no especifica la clave primaria, Zend_Db_Table_Abstract
intenta descubrir la clave primaria basándose en la información proporcionada por el
método describeTable()´.
![]() |
Nota |
|---|---|
Toda clase de tabla debe saber qué columnas se pueden usar para identificar filas
de forma unívoca. Si no se especifican columnas de clave primaria en la definición
de la clase de tabla o en los argumentos del constructor de la tabla, ni se
descubren en los metadatos de la tabla proporcionados por
|
Cuando crea una instancia de una clase de tabla, el constructor invoca un conjunto de métodos protegidos que inicializan los metadatos de la tabla. Puede extender cualquiera de estos métodos para definir metadatos de forma explícita. Recuerde invocar el método del mismo nombre en la clase padre al final de su método.
Ejemplo 27.86. Ejemplo de sobrescritura del método _setupTableName()
class Bugs extends Zend_Db_Table_Abstract
{
protected function _setupTableName()
{
$this->_name = 'bugs';
parent::_setupTableName();
}
}
Los métodos de configuración que puede sobrescribir son los siguientes:
_setupDatabaseAdapter()comprueba que se ha proporcionado un adaptador; obtiene un adaptador por defecto del registro si es necesario. Al sobrescribir este método, puede establecer un adaptador de base de datos desde alguna otra fuente._setupTableName()establece por defecto el nombre de la tabla como el nombre de la clase. Al sobrescribir este método, puede establecer el nombre de la tabla antes de que se ejecute este comportamiento por defecto._setupMetadata()establece el esquema si el nombre de la tabla contiene el patrón "schema.table"; invocadescribeTable()para obtener información de metadatos; establece por defecto el array$_colscon las columnas reportadas pordescribeTable(). Al sobrescribir este método, puede especificar las columnas._setupPrimaryKey()establece por defecto las columnas de la clave primaria como las reportadas pordescribeTable(); comprueba que las columnas de la clave primaria están incluidas en el array$_cols. Al sobrescribir este método, puede especificar las columnas de la clave primaria.
Si la lógica específica de la aplicación necesita inicializarse cuando se construye
una clase de tabla, puede optar por mover sus tareas al método
init(), el cual se invoca después de que se hayan procesado
todos los metadatos de la tabla. Esto se recomienda frente al método
__construct() si no necesita alterar los metadatos de ninguna
forma programática.
Ejemplo 27.87. Ejemplo de uso del método init()
class Bugs extends Zend_Db_Table_Abstract
{
protected $_observer;
public function init()
{
$this->_observer = new MyObserverClass();
}
}
Antes de usar una clase de tabla, cree una instancia usando su constructor. El argumento del constructor es un array de opciones. La opción más importante para un constructor de tabla es la instancia del adaptador de base de datos, que representa una conexión activa a un RDBMS. Hay tres formas de especificar el adaptador de base de datos a una clase de tabla, y estas tres formas se describen a continuación:
La primera forma de proporcionar un adaptador de base de datos a una clase de tabla es
pasándolo como un objeto de tipo Zend_Db_Adapter_Abstract en el
array de opciones, identificado por la clave 'db'.
Ejemplo 27.88. Ejemplo de construcción de una tabla usando un objeto adaptador
$db = Zend_Db::factory('PDO_MYSQL', $options);
$table = new Bugs(array('db' => $db));
La segunda forma de proporcionar un adaptador de base de datos a una clase de tabla es
declarando un objeto de tipo Zend_Db_Adapter_Abstract como
adaptador de base de datos por defecto para todas las instancias posteriores de tablas en su
aplicación. Puede hacer esto con el método estático
Zend_Db_Table_Abstract::setDefaultAdapter(). El argumento
es un objeto de tipo Zend_Db_Adapter_Abstract.
Ejemplo 27.89. Ejemplo de construcción de una tabla usando el adaptador por defecto
$db = Zend_Db::factory('PDO_MYSQL', $options);
Zend_Db_Table_Abstract::setDefaultAdapter($db);
// Más tarde...
$table = new Bugs();
Puede resultar conveniente crear el objeto adaptador de base de datos en un lugar central de su aplicación, como el bootstrap, y luego almacenarlo como el adaptador por defecto. Esto le proporciona un medio para asegurarse de que la instancia del adaptador es la misma en toda su aplicación. Sin embargo, establecer un adaptador por defecto se limita a una única instancia de adaptador.
La tercera forma de proporcionar un adaptador de base de datos a una clase de tabla es
pasando una cadena en el array de opciones, también identificada por la clave
'db'. La cadena se usa como clave para la instancia estática
Zend_Registry, donde la entrada en esa clave es un objeto de
tipo Zend_Db_Adapter_Abstract.
Ejemplo 27.90. Ejemplo de construcción de una tabla usando una clave de registro
$db = Zend_Db::factory('PDO_MYSQL', $options);
Zend_Registry::set('my_db', $db);
// Más tarde...
$table = new Bugs(array('db' => 'my_db'));
Al igual que al establecer el adaptador por defecto, esto le proporciona el medio para asegurarse de que se usa la misma instancia de adaptador en toda su aplicación. Usar el registro es más flexible, porque puede almacenar más de una instancia de adaptador. Una instancia de adaptador dada es específica de una determinada marca de RDBMS e instancia de base de datos. Si su aplicación necesita acceder a múltiples bases de datos o incluso a múltiples marcas de base de datos, entonces necesita usar múltiples adaptadores.
Puede usar el objeto tabla para insertar filas en la tabla de base de datos en la que se
basa el objeto tabla. Use el método insert() de su objeto tabla.
El argumento es un array asociativo, que asigna nombres de columna a valores.
Ejemplo 27.91. Ejemplo de inserción en una tabla
$table = new Bugs();
$data = array(
'created_on' => '2007-03-22',
'bug_description' => 'Something wrong',
'bug_status' => 'NEW'
);
$table->insert($data);
Por defecto, los valores en su array de datos se insertan como valores literales, usando
parámetros. Si necesita que se traten como expresiones SQL, debe
asegurarse de que se distinguen de las cadenas normales. Use un objeto de tipo
Zend_Db_Expr para ello.
Ejemplo 27.92. Ejemplo de inserción de expresiones en una tabla
$table = new Bugs();
$data = array(
'created_on' => new Zend_Db_Expr('CURDATE()'),
'bug_description' => 'Something wrong',
'bug_status' => 'NEW'
);
En los ejemplos de inserción de filas anteriores, se asume que la tabla tiene una
clave primaria autoincremental. Este es el comportamiento por defecto de
Zend_Db_Table_Abstract, pero también existen otros tipos de claves
primarias. Las siguientes secciones describen cómo dar soporte a diferentes tipos de claves primarias.
Una clave primaria autoincremental genera un valor entero único para usted si
omite la columna de clave primaria en su sentencia SQL
INSERT.
En Zend_Db_Table_Abstract, si define la variable protegida
$_sequence con el valor booleano
TRUE, entonces la clase asume que la tabla tiene una
clave primaria autoincremental.
Ejemplo 27.93. Ejemplo de declaración de una tabla con clave primaria autoincremental
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
// This is the default in the Zend_Db_Table_Abstract class;
// you do not need to define this.
protected $_sequence = true;
}
MySQL, Microsoft SQL Server y SQLite son ejemplos de marcas de RDBMS que admiten claves primarias autoincrementales.
PostgreSQL tiene una notación SERIAL que define implícitamente
una secuencia basada en el nombre de la tabla y la columna, y usa la secuencia para
generar valores de clave para las nuevas filas. IBM
DB2 tiene una notación IDENTITY
que funciona de forma similar. Si usa cualquiera de estas notaciones, trate su clase
Zend_Db_Table como si tuviera una columna autoincremental
respecto a la declaración de la variable miembro $_sequence
como TRUE.
Una secuencia es un objeto de base de datos que genera un valor único, que puede usarse como valor de clave primaria en una o más tablas de la base de datos.
Si define $_sequence como una cadena, entonces
Zend_Db_Table_Abstract asume que la cadena nombra un objeto de
secuencia en la base de datos. La secuencia se invoca para generar un nuevo valor, y este
valor se usa en la operación INSERT.
Ejemplo 27.94. Ejemplo de declaración de una tabla con una secuencia
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
protected $_sequence = 'bug_sequence';
}
Oracle, PostgreSQL e IBM DB2 son ejemplos de marcas de RDBMS que admiten objetos de secuencia en la base de datos.
PostgreSQL e IBM DB2 también tienen sintaxis que define secuencias de forma implícita y asociada a columnas. Si usa esta notación, trate la tabla como si tuviera una columna de clave autoincremental. Defina el nombre de la secuencia como una cadena solo en los casos en los que invocaría la secuencia de forma explícita para obtener el siguiente valor de clave.
Algunas tablas tienen una clave natural. Esto significa que la clave no la genera automáticamente la tabla ni una secuencia. Debe especificar el valor para la clave primaria en este caso.
Si define $_sequence con el valor booleano
FALSE, entonces Zend_Db_Table_Abstract
asume que la tabla tiene una clave primaria natural. Debe proporcionar valores para las
columnas de la clave primaria en el array de datos del método
insert(), o de lo contrario este método lanza una
Zend_Db_Table_Exception.
Ejemplo 27.95. Ejemplo de declaración de una tabla con una clave natural
class BugStatus extends Zend_Db_Table_Abstract
{
protected $_name = 'bug_status';
protected $_sequence = false;
}
![]() |
Nota |
|---|---|
Todas las marcas de RDBMS admiten tablas con claves naturales. Ejemplos de tablas que a menudo se declaran con claves naturales son las tablas de consulta (lookup), las tablas de intersección en relaciones muchos a muchos, o la mayoría de las tablas con claves primarias compuestas. |
Puede actualizar filas en una tabla de base de datos usando el método
update() de una clase de tabla. Este método toma dos argumentos: un
array asociativo de columnas a cambiar y los nuevos valores que asignar a estas columnas; y una
expresión SQL que se usa en una cláusula WHERE,
como criterio para las filas a cambiar en la operación UPDATE.
Ejemplo 27.96. Ejemplo de actualización de filas en una tabla
$table = new Bugs();
$data = array(
'updated_on' => '2007-03-23',
'bug_status' => 'FIXED'
);
$where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
$table->update($data, $where);
Dado que el método update() de la tabla delega en el método
update()
del adaptador de base de datos, el segundo argumento puede ser un array de expresiones
SQL. Las expresiones se combinan como términos booleanos usando un
operador AND.
![]() |
Nota |
|---|---|
Los valores e identificadores en la expresión SQL no se
entrecomillan automáticamente. Si tiene valores o identificadores que requieran
entrecomillado, usted es responsable de hacerlo. Use los métodos
|
Puede eliminar filas de una tabla de base de datos usando el método
delete(). Este método toma un argumento, que es una expresión
SQL que se usa en una cláusula WHERE, como
criterio para las filas a eliminar.
Ejemplo 27.97. Ejemplo de eliminación de filas de una tabla
$table = new Bugs();
$where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
$table->delete($where);
Dado que el método delete() de la tabla delega en el método
delete()
del adaptador de base de datos, el argumento también puede ser un array de expresiones
SQL. Las expresiones se combinan como términos booleanos usando un
operador AND.
![]() |
Nota |
|---|---|
Los valores e identificadores en la expresión SQL no se
entrecomillan automáticamente. Si tiene valores o identificadores que requieran
entrecomillado, usted es responsable de hacerlo. Use los métodos
|
Puede consultar la tabla de base de datos en busca de filas que coincidan con valores
específicos en la clave primaria, usando el método find(). El
primer argumento de este método es bien un único valor, bien un array de valores a comparar
con la clave primaria de la tabla.
Ejemplo 27.98. Ejemplo de búsqueda de filas por valores de clave primaria
$table = new Bugs(); // Find a single row // Returns a Rowset $rows = $table->find(1234); // Find multiple rows // Also returns a Rowset $rows = $table->find(array(1234, 5678));
Si especifica un único valor, el método devuelve como máximo una fila, porque una clave primaria no puede tener valores duplicados y hay como máximo una fila en la tabla de base de datos que coincide con el valor que especifique. Si especifica varios valores en un array, el método devuelve como máximo tantas filas como el número de valores distintos que especifique.
El método find() puede devolver menos filas que el número de
valores que especifique para la clave primaria, si algunos de los valores no coinciden con
ninguna fila de la tabla de base de datos. El método incluso puede devolver cero filas. Dado
que el número de filas devueltas es variable, el método find()
devuelve un objeto de tipo Zend_Db_Table_Rowset_Abstract.
Si la clave primaria es compuesta, es decir, consta de varias columnas, puede
especificar las columnas adicionales como argumentos adicionales al método
find(). Debe proporcionar tantos argumentos como el número de
columnas de la clave primaria de la tabla.
Para encontrar múltiples filas en una tabla con clave primaria compuesta, proporcione un array para cada uno de los argumentos. Todos estos arrays deben tener el mismo número de elementos. Los valores de cada array se forman en tuplas en orden; por ejemplo, el primer elemento de todos los argumentos array define el primer valor de clave primaria compuesta, luego los segundos elementos de todos los arrays definen el segundo valor de clave primaria compuesta, y así sucesivamente.
Ejemplo 27.99. Ejemplo de búsqueda de filas por valores de clave primaria compuesta
La llamada a find() siguiente, para encontrar coincidencias
de múltiples filas, puede coincidir con dos filas en la base de datos. La primera fila
debe tener el valor de clave primaria (1234, 'ABC'), y la segunda fila debe tener el valor
de clave primaria (5678, 'DEF').
class BugsProducts extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs_products';
protected $_primary = array('bug_id', 'product_id');
}
$table = new BugsProducts();
// Find a single row with a compound primary key
// Returns a Rowset
$rows = $table->find(1234, 'ABC');
// Find multiple rows with compound primary keys
// Also returns a Rowset
$rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
![]() |
Advertencia |
|---|---|
|
La API para operaciones de recuperación se ha sustituido
para permitir que un objeto Las siguientes sentencias son todas legales y funcionalmente idénticas, sin embargo se recomienda actualizar su código para aprovechar el nuevo uso siempre que sea posible.
/**
* Fetching a rowset
*/
$rows = $table->fetchAll(
'bug_status = "NEW"',
'bug_id ASC',
10,
0
);
$rows = $table->fetchAll(
$table->select()
->where('bug_status = ?', 'NEW')
->order('bug_id ASC')
->limit(10, 0)
);
// or with binding
$rows = $table->fetchAll(
$table->select()
->where('bug_status = :status')
->bind(array(':status'=>'NEW')
->order('bug_id ASC')
->limit(10, 0)
);
/**
* Fetching a single row
*/
$row = $table->fetchRow(
'bug_status = "NEW"',
'bug_id ASC'
);
$row = $table->fetchRow(
$table->select()
->where('bug_status = ?', 'NEW')
->order('bug_id ASC')
);
// or with binding
$row = $table->fetchRow(
$table->select()
->where('bug_status = :status')
->bind(array(':status'=>'NEW')
->order('bug_id ASC')
);
|
El objeto Zend_Db_Table_Select es una extensión del objeto
Zend_Db_Select que aplica restricciones específicas a
una consulta. Las mejoras y restricciones son:
Puede optar por devolver un subconjunto de columnas dentro de una consulta fetchRow o fetchAll. Esto puede proporcionar beneficios de optimización cuando no es deseable devolver un gran conjunto de resultados para todas las columnas.
Puede especificar columnas que evalúen expresiones dentro de la tabla seleccionada. Sin embargo, esto significará que la fila o rowset devuelto será de readOnly y no se podrá usar para operaciones
save(). UnZend_Db_Table_Rowcon estado readOnly lanzará una excepción si se intenta una operaciónsave().Puede permitir cláusulas
JOINen una consulta select para permitir búsquedas multitabla.No puede especificar columnas de una tabla unida (JOINed) para que se devuelvan en una fila o rowset. Hacerlo desencadenará un error de PHP. Esto se hizo para asegurar que se mantenga la integridad de
Zend_Db_Table. Es decir, unZend_Db_Table_Rowsolo debería referenciar columnas derivadas de su tabla padre.
Ejemplo 27.100. Uso simple
$table = new Bugs();
$select = $table->select();
$select->where('bug_status = ?', 'NEW');
$rows = $table->fetchAll($select);
Las interfaces fluidas se implementan en todo el componente, por lo que esto se puede reescribir en una forma más abreviada.
Ejemplo 27.101. Ejemplo de interfaz fluida
$table = new Bugs();
$rows =
$table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
Puede consultar un conjunto de filas usando cualquier criterio distinto de los
valores de la clave primaria, usando el método fetchAll() de la
clase de tabla. Este método devuelve un objeto de tipo
Zend_Db_Table_Rowset_Abstract.
Ejemplo 27.102. Ejemplo de búsqueda de filas mediante una expresión
$table = new Bugs();
$select = $table->select()->where('bug_status = ?', 'NEW');
$rows = $table->fetchAll($select);
También puede pasar criterios de ordenación en una cláusula ORDER
BY, así como valores enteros de cuenta y desplazamiento, usados para que la consulta
devuelva un subconjunto específico de filas. Estos valores se usan en una cláusula
LIMIT, o en lógica equivalente para marcas de
RDBMS que no admiten la sintaxis
LIMIT.
Ejemplo 27.103. Ejemplo de búsqueda de filas mediante una expresión
$table = new Bugs();
$order = 'bug_id';
// Return the 21st through 30th rows
$count = 10;
$offset = 20;
$select = $table->select()->where('bug_status = ?', 'NEW')
->order($order)
->limit($count, $offset);
$rows = $table->fetchAll($select);
Todos los argumentos anteriores son opcionales. Si omite la cláusula
ORDER, el conjunto de resultados incluye filas de la tabla en un
orden impredecible. Si no se establece ninguna cláusula LIMIT,
recupera todas las filas de la tabla que coincidan con la cláusula
WHERE.
Para solicitudes más específicas y optimizadas, puede que desee limitar el número de
columnas devueltas en una fila o rowset. Esto se puede lograr pasando una cláusula
FROM al objeto select. El primer argumento de la cláusula
FROM es idéntico al de un objeto
Zend_Db_Select, con la adición de poder pasar
una instancia de Zend_Db_Table_Abstract y hacer que
determine automáticamente el nombre de la tabla.
Ejemplo 27.104. Recuperar columnas específicas
$table = new Bugs();
$select = $table->select();
$select->from($table, array('bug_id', 'bug_description'))
->where('bug_status = ?', 'NEW');
$rows = $table->fetchAll($select);
![]() |
Importante |
|---|---|
El rowset contiene filas que siguen siendo 'válidas': simplemente contienen un
subconjunto de las columnas de una tabla. Si se invoca un método
|
También puede especificar expresiones dentro de una cláusula FROM
y hacer que estas se devuelvan como una fila o rowset readOnly. En este ejemplo
devolveremos filas de la tabla bugs que muestran un agregado del número de bugs nuevos
reportados por individuos. Observe la cláusula GROUP. La columna
'count' se pondrá a disposición de la fila para su evaluación y se puede acceder a ella
como si fuera parte del esquema.
Ejemplo 27.105. Recuperar expresiones como columnas
$table = new Bugs();
$select = $table->select();
$select->from($table,
array('COUNT(reported_by) as `count`', 'reported_by'))
->where('bug_status = ?', 'NEW')
->group('reported_by');
$rows = $table->fetchAll($select);
También puede usar una tabla de consulta (lookup) como parte de su consulta para refinar aún más sus operaciones de recuperación. En este ejemplo, la tabla accounts se consulta como parte de una búsqueda de todos los bugs nuevos reportados por 'Bob'.
Ejemplo 27.106. Usar una tabla de consulta para refinar los resultados de fetchAll()
$table = new Bugs();
// retrieve with from part set, important when joining
$select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
$select->setIntegrityCheck(false)
->where('bug_status = ?', 'NEW')
->join('accounts', 'accounts.account_name = bugs.reported_by')
->where('accounts.account_name = ?', 'Bob');
$rows = $table->fetchAll($select);
Zend_Db_Table_Select se usa principalmente para restringir y
validar, de modo que pueda aplicar el criterio para una consulta SELECT
legal. Sin embargo, puede haber ciertos casos en los que necesite la flexibilidad del
componente Zend_Db_Table_Row y no necesite una fila escribible o
eliminable. Para este caso de uso específico, es posible recuperar una fila o
rowset pasando un valor FALSE a
setIntegrityCheck(). La fila o rowset resultante se
devolverá como una fila 'bloqueada' (lo que significa que save(),
delete() y cualquier método de establecimiento de campo lanzarán
una excepción).
Ejemplo 27.107. Eliminar la comprobación de integridad en Zend_Db_Table_Select para permitir filas JOINed
$table = new Bugs();
$select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->setIntegrityCheck(false);
$select->where('bug_status = ?', 'NEW')
->join('accounts',
'accounts.account_name = bugs.reported_by',
'account_name')
->where('accounts.account_name = ?', 'Bob');
$rows = $table->fetchAll($select);
Puede consultar una única fila usando criterios similares a los del método
fetchAll().
Ejemplo 27.108. Ejemplo de búsqueda de una única fila mediante una expresión
$table = new Bugs();
$select = $table->select()->where('bug_status = ?', 'NEW')
->order('bug_id');
$row = $table->fetchRow($select);
Este método devuelve un objeto de tipo Zend_Db_Table_Row_Abstract.
Si el criterio de búsqueda que especificó no coincide con ninguna fila de la tabla de base de
datos, entonces fetchRow() devuelve el valor
NULL de PHP.
La clase Zend_Db_Table_Abstract proporciona cierta información
sobre sus metadatos. El método info() devuelve una estructura de
array con información sobre la tabla, sus columnas y clave primaria, y otros metadatos.
Ejemplo 27.109. Ejemplo de obtención del nombre de la tabla
$table = new Bugs(); $info = $table->info(); echo "The table name is " . $info['name'] . "\n";
Las claves del array devuelto por el método info() se
describen a continuación:
name => el nombre de la tabla.
cols => un array, con los nombres de las columnas de la tabla.
primary => un array, con los nombres de las columnas de la clave primaria.
metadata => un array asociativo, que asigna nombres de columna a información sobre las columnas. Esta es la información devuelta por el método
describeTable().rowClass => el nombre de la clase concreta usada para los objetos Row devueltos por los métodos de esta instancia de tabla. Por defecto es
Zend_Db_Table_Row.rowsetClass => el nombre de la clase concreta usada para los objetos Rowset devueltos por los métodos de esta instancia de tabla. Por defecto es
Zend_Db_Table_Rowset.referenceMap => un array asociativo, con información sobre las referencias de esta tabla a cualquier tabla padre. Consulte este capítulo.
dependentTables => un array de nombres de clase de las tablas que hacen referencia a esta tabla. Consulte este capítulo.
schema => el nombre del esquema (o base de datos o tablespace) de esta tabla.
Por defecto, Zend_Db_Table_Abstract consulta la
base de datos subyacente en busca de metadatos de la
tabla cada vez que se necesitan esos datos para realizar operaciones de tabla.
El objeto tabla obtiene los metadatos de la tabla desde la
base de datos usando el método describeTable() del adaptador.
Las operaciones que requieren esta introspección incluyen:
insert()find()info()
En algunas circunstancias, particularmente cuando se instancian muchos objetos de tabla contra la misma tabla de base de datos, consultar la base de datos para obtener los metadatos de la tabla en cada instancia puede resultar indeseable desde el punto de vista del rendimiento. En tales casos, los usuarios pueden beneficiarse de almacenar en caché los metadatos de la tabla recuperados de la base de datos.
Hay dos formas principales en las que un usuario puede aprovechar el almacenamiento en caché de metadatos de la tabla:
Invocar
Zend_Db_Table_Abstract::setDefaultMetadataCache()- Esto permite a un desarrollador establecer una vez el objeto de caché por defecto a usar en todas las clases de tabla.Configurar
Zend_Db_Table_Abstract::__construct()- Esto permite a un desarrollador establecer el objeto de caché a usar para una instancia particular de clase de tabla.
En ambos casos, la especificación de caché debe ser bien NULL (es
decir, no usar caché), bien una instancia de
Zend_Cache_Core.
Los métodos se pueden usar conjuntamente cuando sea deseable tener tanto una caché de
metadatos por defecto como la capacidad de cambiar la caché para objetos de tabla
individuales.
Ejemplo 27.110. Usar una caché de metadatos por defecto para todos los objetos de tabla
El siguiente código muestra cómo establecer una caché de metadatos por defecto para usarla con todos los objetos de tabla:
// First, set up the Cache
$frontendOptions = array(
'automatic_serialization' => true
);
$backendOptions = array(
'cache_dir' => 'cacheDir'
);
$cache = Zend_Cache::factory('Core',
'File',
$frontendOptions,
$backendOptions);
// Next, set the cache to be used with all table objects
Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
// A table class is also needed
class Bugs extends Zend_Db_Table_Abstract
{
// ...
}
// Each instance of Bugs now uses the default metadata cache
$bugs = new Bugs();
Ejemplo 27.111. Usar una caché de metadatos para un objeto de tabla específico
El siguiente código muestra cómo establecer una caché de metadatos para una instancia de objeto de tabla específica:
// First, set up the Cache
$frontendOptions = array(
'automatic_serialization' => true
);
$backendOptions = array(
'cache_dir' => 'cacheDir'
);
$cache = Zend_Cache::factory('Core',
'File',
$frontendOptions,
$backendOptions);
// A table class is also needed
class Bugs extends Zend_Db_Table_Abstract
{
// ...
}
// Configure an instance upon instantiation
$bugs = new Bugs(array('metadataCache' => $cache));
![]() |
Serialización automática con el frontend de caché |
|---|---|
Dado que la información devuelta por el método |
Aunque los ejemplos anteriores usan Zend_Cache_Backend_File, los
desarrolladores pueden usar el backend de caché que resulte apropiado para la situación.
Consulte Zend_Cache para más información.
Para llevar el almacenamiento en caché de metadatos un paso más allá, también puede optar por codificar los metadatos de forma fija (hardcode). En este caso particular, sin embargo, cualquier cambio en el esquema de la tabla requerirá un cambio en su código. Por ello, solo se recomienda para quienes estén optimizando para el uso en producción.
La estructura de metadatos es la siguiente:
protected $_metadata = array(
'<column_name>' => array(
'SCHEMA_NAME' => <string>,
'TABLE_NAME' => <string>,
'COLUMN_NAME' => <string>,
'COLUMN_POSITION' => <int>,
'DATA_TYPE' => <string>,
'DEFAULT' => NULL|<value>,
'NULLABLE' => <bool>,
'LENGTH' => <string - length>,
'SCALE' => NULL|<value>,
'PRECISION' => NULL|<value>,
'UNSIGNED' => NULL|<bool>,
'PRIMARY' => <bool>,
'PRIMARY_POSITION' => <int>,
'IDENTITY' => <bool>,
),
// additional columns...
);
Una forma fácil de obtener los valores adecuados es usar la caché de metadatos, y luego deserializar los valores almacenados en la caché.
Puede desactivar esta optimización desactivando el indicador metadataCacheInClass:
// At instantiation:
$bugs = new Bugs(array('metadataCacheInClass' => false));
// Or later:
$bugs->setMetadataCacheInClass(false);
El indicador está activado por defecto, lo que asegura que el
array $_metadata solo se rellene una vez por
instancia.
Por defecto, los métodos de la clase Table devuelven un Rowset en instancias de la
clase concreta Zend_Db_Table_Rowset, y los Rowsets contienen una
colección de instancias de la clase concreta Zend_Db_Table_Row.
Puede especificar una clase alternativa para usar en cualquiera de ellas, pero deben ser
clases que extiendan Zend_Db_Table_Rowset_Abstract y
Zend_Db_Table_Row_Abstract, respectivamente.
Puede especificar las clases Row y Rowset usando el array de opciones del constructor de la tabla, en las claves 'rowClass' y 'rowsetClass' respectivamente. Especifique los nombres de las clases usando cadenas.
Ejemplo 27.112. Ejemplo de especificación de las clases Row y Rowset
class My_Row extends Zend_Db_Table_Row_Abstract
{
...
}
class My_Rowset extends Zend_Db_Table_Rowset_Abstract
{
...
}
$table = new Bugs(
array(
'rowClass' => 'My_Row',
'rowsetClass' => 'My_Rowset'
)
);
$where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
// Returns an object of type My_Rowset,
// containing an array of objects of type My_Row.
$rows = $table->fetchAll($where);
Puede cambiar las clases especificándolas con los métodos
setRowClass() y setRowsetClass().
Esto se aplica a las filas y rowsets creados posteriormente; no cambia la clase de
ninguna fila o rowset que haya creado previamente.
Ejemplo 27.113. Ejemplo de cambio de las clases Row y Rowset
$table = new Bugs();
$where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
// Returns an object of type Zend_Db_Table_Rowset
// containing an array of objects of type Zend_Db_Table_Row.
$rowsStandard = $table->fetchAll($where);
$table->setRowClass('My_Row');
$table->setRowsetClass('My_Rowset');
// Returns an object of type My_Rowset,
// containing an array of objects of type My_Row.
$rowsCustom = $table->fetchAll($where);
// The $rowsStandard object still exists, and it is unchanged.
Para más información sobre las clases Row y Rowset, consulte este capítulo y este otro.
Puede sobrescribir los métodos insert() y
update() en su clase de tabla. Esto le da la
oportunidad de implementar código personalizado que se ejecuta antes de realizar la
operación de base de datos. Asegúrese de invocar el método de la clase padre cuando haya
terminado.
Ejemplo 27.114. Lógica personalizada para gestionar marcas de tiempo
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
public function insert(array $data)
{
// add a timestamp
if (empty($data['created_on'])) {
$data['created_on'] = time();
}
return parent::insert($data);
}
public function update(array $data, $where)
{
// add a timestamp
if (empty($data['updated_on'])) {
$data['updated_on'] = time();
}
return parent::update($data, $where);
}
}
También puede sobrescribir el método delete().
Puede implementar métodos de consulta personalizados en su clase de tabla, si tiene
necesidad frecuente de realizar consultas contra esta tabla con criterios específicos. La
mayoría de las consultas se pueden escribir usando fetchAll(),
pero esto requiere que duplique código para formar las condiciones de la consulta si
necesita ejecutar la consulta en varios lugares de su aplicación. Por lo tanto, puede
resultar conveniente implementar un método en la clase de tabla para realizar consultas de
uso frecuente contra esta tabla.
Ejemplo 27.115. Método personalizado para buscar bugs por estado
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
public function findByStatus($status)
{
$where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
return $this->fetchAll($where, 'bug_id');
}
}
Algunas personas prefieren que el nombre de la clase de tabla coincida con un nombre de tabla en el RDBMS mediante una transformación de cadena llamada inflexión.
Por ejemplo, si el nombre de su clase de tabla es "BugsProducts", coincidiría
con la tabla física en la base de datos llamada "bugs_products", si
omite la declaración explícita de la propiedad de clase $_name.
En este mapeo de inflexión, el nombre de la clase escrito en formato "CamelCase" se
transformaría a minúsculas, y las palabras se separarían con un guion bajo.
Puede especificar el nombre de la tabla de base de datos independientemente del nombre
de la clase declarando el nombre de la tabla con la propiedad de clase
$_name en cada una de sus clases de tabla.
Zend_Db_Table_Abstract no realiza ninguna inflexión para
mapear el nombre de la clase al nombre de la tabla. Si omite la declaración de
$_name en su clase de tabla, la clase se mapea a una tabla de base
de datos que coincide exactamente con el nombre de la clase.
Es inapropiado transformar identificadores de la base de datos, porque esto puede
producir ambigüedad o hacer que algunos identificadores sean inaccesibles. Usar los
identificadores SQL exactamente tal y como aparecen en la
base de datos hace que Zend_Db_Table_Abstract sea a la vez más
simple y más flexible.
Si prefiere usar inflexión, entonces debe implementar la transformación usted
mismo, sobrescribiendo el método _setupTableName() en sus
clases de tabla. Una forma de hacerlo es definir una clase abstracta que extienda
Zend_Db_Table_Abstract, y luego hacer que el resto de sus tablas
extiendan su nueva clase abstracta.
Ejemplo 27.116. Ejemplo de una clase de tabla abstracta que implementa inflexión
abstract class MyAbstractTable extends Zend_Db_Table_Abstract
{
protected function _setupTableName()
{
if (!$this->_name) {
$this->_name = myCustomInflector(get_class($this));
}
parent::_setupTableName();
}
}
class BugsProducts extends MyAbstractTable
{
}
Usted es responsable de escribir las funciones para realizar la transformación de inflexión. Zend Framework no proporciona tal función.
![[Note]](images/note.png)
![[Warning]](images/warning.png)
![[Important]](images/important.png)