ORM con Zend Framework
Por zsamer en Junio 28, 2008
En el post anterior había prometido escribir un articulo sobre implementar ORM con Zend Framework.
El mapeo objeto-relacional es una técnica de programación para convertir datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a objetos y el utilizado en una base de datos relacional. En la práctica esto crea una base de datos orientada a objetos virtual, por sobre la base de datos relacional. Si estas interesado en como implementar esta técnica con Zend_Db_Table Relationships entonces continua leyendo.
Las tablas tienen relaciones unas con otras en una base de datos relacional. Un entidad en una tabla puede ser asociada o linkeada hacia una o más entidades en otra tabla usando restricciones de integridad referencial (referential integrity constraints) definida en el esquema de base de datos.
En nuestro caso vamos a utilizar Mysql, por lo tanto es fundamental utilizar InnoDB ya que soporta integridad referencial en Mysql AB.
Creando nuestras tablas en la base de datos
En la imagen de abajo muestra un diagrama que representa las relaciones de nuestras tablas en la base de datos.
Nos damos cuenta de que tenemos variadas relaciones, por ejemplo BugsProducts tiene muchos-a-muchos respecto a la tabla Products y a Bugs porque para un determinado bug puede ser relevante para múltiples productos, y por supuesto un determinado productos puede tener múltiples bugs.
Sin embargo la Tabla Bugs esta asociada a Muchos BugsProducts y solo uno Accounts en tres relaciones distintas reported_by, assigned_to y verified_by. Mientras que Accounts puede tener asignado mas de un Bugs (dentro de sus tres tipos de relaciones).
También notamos que la tabla bugs contiene múltiples foreign key referenciadas a la tabla accounts. Cada una de estas foreign keys hacen referencia a diferentes registros en la tabla accounts para un determinado bug.
A continuación comparto el SQL de la base de datos, en el ejemplo trataremos con Mysql, aunque podría ser cualquier otro motor de base de datos ya que Zend Framework soporta a la mayoría de los motores.
-
--
-
-- Estructura de tabla para la tabla `accounts`
-
--
-
-
DROP TABLE IF EXISTS `accounts`;
-
CREATE TABLE IF NOT EXISTS `accounts` (
-
`account_name` varchar(100) NOT NULL COMMENT 'Account Name',
-
PRIMARY KEY (`account_name`)
-
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Account Table';
-
-
--
-
-- Volcar la base de datos para la tabla `accounts`
-
--
-
-
INSERT INTO `accounts` (`account_name`) VALUES
-
('admin'),
-
('zsamer');
-
-- --------------------------------------------------------
-
-
--
-
-- Estructura de tabla para la tabla `bugs`
-
--
-
-
DROP TABLE IF EXISTS `bugs`;
-
CREATE TABLE IF NOT EXISTS `bugs` (
-
`bug_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Bug Id',
-
`bug_description` varchar(100) NOT NULL COMMENT 'Bug Description',
-
`bug_status` varchar(20) NOT NULL COMMENT 'Bug Status',
-
`reported_by` varchar(100) NOT NULL COMMENT 'Reported By',
-
`assigned_to` varchar(100) NOT NULL COMMENT 'Assigned To',
-
`verified_by` varchar(100) NOT NULL COMMENT 'Verified By',
-
PRIMARY KEY (`bug_id`),
-
KEY `FK_accounts_reported_by` (`reported_by`),
-
KEY `FK_accounts_assigned_to` (`assigned_to`),
-
KEY `FK_accounts_verified_by` (`verified_by`)
-
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Bugs Table';
-
-
--
-
-- Volcar la base de datos para la tabla `bugs`
-
--
-
-
INSERT INTO `bugs` (`bug_id`, `bug_description`, `bug_status`, `reported_by`, `assigned_to`, `verified_by`) VALUES
-
(1, 'Sin suela', 'activo', 'admin', 'admin', 'zsamer'),
-
(2, 'Descosedura', 'NEW', 'zsamer', 'admin', 'zsamer');
-
-
-- --------------------------------------------------------
-
-
--
-
-- Estructura de tabla para la tabla `bugs_products`
-
--
-
-
DROP TABLE IF EXISTS `bugs_products`;
-
CREATE TABLE IF NOT EXISTS `bugs_products` (
-
`bug_id` int(11) NOT NULL COMMENT 'Bug Id',
-
`product_id` int(11) NOT NULL COMMENT 'Product Id',
-
PRIMARY KEY (`bug_id`,`product_id`),
-
KEY `product_id` (`product_id`)
-
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Bugs Products Table';
-
-
--
-
-- Volcar la base de datos para la tabla `bugs_products`
-
--
-
-
INSERT INTO `bugs_products` (`bug_id`, `product_id`) VALUES
-
(1, 1),
-
(2, 2),
-
(1, 3),
-
(2, 3),
-
(2, 4);
-
-
-- --------------------------------------------------------
-
-
--
-
-- Estructura de tabla para la tabla `products`
-
--
-
-
DROP TABLE IF EXISTS `products`;
-
CREATE TABLE IF NOT EXISTS `products` (
-
`product_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Product Id',
-
`product_name` varchar(100) NOT NULL COMMENT 'Product Name',
-
PRIMARY KEY (`product_id`)
-
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Product Table';
-
-
--
-
-- Volcar la base de datos para la tabla `products`
-
--
-
-
INSERT INTO `products` (`product_id`, `product_name`) VALUES
-
(1, 'Zapatos'),
-
(2, 'Pantalones'),
-
(3, 'Zapatillas'),
-
(4, 'Poleras');
-
-
--
-
-- Filtros para la tabla `bugs`
-
--
-
ALTER TABLE `bugs`
-
ADD CONSTRAINT `bugs_ibfk_3` FOREIGN KEY (`verified_by`) REFERENCES `accounts` (`account_name`),
-
ADD CONSTRAINT `bugs_ibfk_1` FOREIGN KEY (`reported_by`) REFERENCES `accounts` (`account_name`),
-
ADD CONSTRAINT `bugs_ibfk_2` FOREIGN KEY (`assigned_to`) REFERENCES `accounts` (`account_name`);
-
-
--
-
-- Filtros para la tabla `bugs_products`
-
--
-
ALTER TABLE `bugs_products`
-
ADD CONSTRAINT `bugs_products_ibfk_2` FOREIGN KEY (`product_id`) REFERENCES `products` (`product_id`) ON DELETE CASCADE,
-
ADD CONSTRAINT `bugs_products_ibfk_1` FOREIGN KEY (`bug_id`) REFERENCES `bugs` (`bug_id`);
Definiendo las relaciones en los Modelos
Definiendo clases por cada tabla de la base de datos, extendiendo a la clase abstracta Zend_Db_Table_Abstract.
-
<?php
-
class Accounts extends Zend_Db_Table_Abstract
-
{
-
protected $_name = 'accounts';
-
}
-
-
class Products extends Zend_Db_Table_Abstract
-
{
-
protected $_name = 'products';
-
}
-
-
class Bugs extends Zend_Db_Table_Abstract
-
{
-
protected $_name = 'bugs';
-
-
-
'columns' => 'reported_by',
-
'refTableClass' => 'Accounts',
-
'refColumns' => 'account_name'
-
),
-
'columns' => 'assigned_to',
-
'refTableClass' => 'Accounts',
-
'refColumns' => 'account_name'
-
),
-
'refTableClass' => 'Accounts',
-
)
-
);
-
}
-
-
class BugsProducts extends Zend_Db_Table_Abstract
-
{
-
protected $_name = 'bugs_products';
-
-
'refTableClass' => 'Bugs',
-
),
-
'refTableClass' => 'Products',
-
)
-
);
-
-
}
Ejemplos de uso
-
public function ejemploUnoAction()
-
{
-
require_once 'Accounts.php';
-
-
$bugsTable = new Bugs();
-
$bug1 = $bugsRowset->current();
-
-
// Specify the reference rule
-
$engineer = $bug1->findParentAccountsByEngineer();
-
-
//Obtenemos al Ingeniero asociado al Bugs currente con status NEW
-
print '<pre>';
-
}
-
-
public function ejemploDosAction()
-
{
-
require_once 'Accounts.php';
-
-
$bugsTable = new Bugs();
-
$bug1 = $bugsRowset->current();
-
-
//Obtenemos al Reporteador asociado al Bugs currente con status NEW
-
//Obtenemos al Reporter ya que por defecto toma al primero en el $_referenceMap, a menos que se indiquemos cual.
-
$reporter = $bug1->findParentAccounts();
-
print '<pre>';
-
}
-
-
public function ejemploTresAction()
-
{
-
require_once 'Accounts.php';
-
-
$accountsTable = new Accounts();
-
$accountsRowset = $accountsTable->find('admin');
-
$user1234 = $accountsRowset->current();
-
$select = $accountsTable->select()->order('reported_by DESC')->limit(3);
-
-
$bugsReportedByUser = $user1234->findDependentRowset('Bugs', 'Engineer', $select);
-
-
// Use the default reference rule
-
$bugsReportedBy = $user1234->findBugs();
-
-
// Specify the reference rule
-
$bugsAssignedTo = $user1234->findBugsByEngineer();
-
-
print '<pre>';
-
-
print '<pre>';
-
-
print '<pre>';
-
}
-
-
public function ejemploCuatroAction()
-
{
-
require_once 'Accounts.php';
-
-
$bugsTable = new Bugs();
-
$bugsRowset = $bugsTable->find(2);
-
$bug1234 = $bugsRowset->current();
-
-
$products = $bug1234->findProductsViaBugsProductsByBug();
-
-
print '<pre>';
-
}
-
-
public function ejemploCincoAction()
-
{
-
require_once 'Accounts.php';
-
-
$bugsTable = new Bugs();
-
$bugsRowset = $bugsTable->find(2);
-
$bug1234 = $bugsRowset->current();
-
-
$products = $bug1234->findManyToManyRowset('Products', 'BugsProducts');
-
-
// Use the default reference rule
-
//$products = $bug1234->findProductsViaBugsProducts();
-
-
// Specify the reference rule
-
$products = $bug1234->findProductsViaBugsProductsByBug();
-
-
print '<pre>';
-
}
Espero que sirva, para más detalle ver el manual, hay mucha información ahi.
Comentarios
2 Responses to “ORM con Zend Framework”
Deja tu comentario


Espero te encuentres muy bien, ojala y pronto saques algo nuevo sobre zendFramework ya que todas tus entradas en el blog an estado muy interesantes.
Gracias ArmaNDO, muy luego viene el próximo, no te preocupes porque tengo pensado al menos sacar 1 o 2 post al mes como mínimo.
Que estés bien,
Andrés.