Foros del Web » Programando para Internet » PHP » Zend »

Zend - MVC - Duda Persistencia / Modelo

Estas en el tema de Zend - MVC - Duda Persistencia / Modelo en el foro de Zend en Foros del Web. Soy principiante en poo, php y Zend, y en mis desarrollos fui probando diferentes formas de hacer las cosas y hoy llegue al punto de ...
  #1 (permalink)  
Antiguo 08/03/2011, 12:52
 
Fecha de Ingreso: diciembre-2010
Mensajes: 13
Antigüedad: 13 años, 11 meses
Puntos: 0
Zend - MVC - Duda Persistencia / Modelo

Soy principiante en poo, php y Zend, y en mis desarrollos fui probando diferentes formas de hacer las cosas y hoy llegue al punto de no saber cual seria la forma mas adecuada para manejar la persistencia.

Tengo claro que se maneja en el modelo y esta puede ser una bd, un webservice o guardar una imagen en un directorio.

Mi duda es desde donde llamar al modelo y si a los metodos de la clase modelo pesarle variables simples o quizás un objeto.

Pongo un ejemplo básico con las posibles formas que encuentro de hacerlo.

Desde que aprendí poo todo es un objeto, por ejemplo si en mi web voy a tratar con productos creo mi clase Producto con sus atributos "Nombre" "descripcion" "precio" etc, ahora bien necesito que esos productos se persistan en una BD y también necesito luego poder recuperarlos de la persistencia.

Desde mi controlador hago la instancia de un objeto producto y a traves de metodos set o desde el constructor cargo el (nombre descripcion y precio), obtenidos seguramente desde un formulario. Bien llego la hora de persistir este producto en la BD y tengo las siguientes opciones:

OPCION[1] Desde el controlador instancio la clase del modelo Productos y llamo al metodo "save" y le paso los parametros ($nombre,$descripcion,$precio).

Clase del Modelo
Código PHP:
class Application_Model_DbTable_Productos extends Zend_Db_Table_Abstract
{
    protected 
$_name 'productos';

     public function 
save($nombre,$descripcion,$precio){  
        
$data = array('nombre'=> $nombre'descripcion' => $descripcion'precio' => $precio);
        
$this->insert($data);
    }
    public function 
search($nombre){  
        
$where $this->select()->where('nombre LIKE %?%'$nombre);
        
$rows $this->fetchAll($where);
    return 
$rows;
    }

Controlador
Código PHP:
public function nuevoAction(){
   
$params $this->getRequest()->getPost();
   
$producto = new My_Producto($params['nombre'],$params['descripcion'],$params['precio'] );

   
$modeloProducto = new Application_Model_DbTable_Productos;              
   
$modeloProducto->save($params['nombre'],$params['descripcion'],$params['precio']);
   
//O 
   
$modeloProducto->save($producto->getNombre(),$producto->getDescripcion(),$producto->getPrecio());
 }
//Luego si quisiera buscar productos con x nombre en la persistencia
public function searchAction(){
   
$params $this->getRequest()->getPost();               
   
$modeloProducto = new Application_Model_DbTable_Productos;
   
$rows $modeloProducto->search($params['nombre']);

   foreach(
$rows as $row){
   
$producto = new My_Producto($row->nombre,$row->descripcion,$row->precio);
   
$colProductos[] = $producto;
   }                       

OPCION[2] Desde el controlador instancio la clase del modelo Productos y llamo al metodo "save" y le paso directamente el objeto Producto

Clase del Modelo
Código PHP:
class Application_Model_DbTable_Productos extends Zend_Db_Table_Abstract
{
    protected 
$_name 'productos';
     public function 
save(My_Producto $producto){  
        
$data = array('nombre'=> $producto->getNombre(), 'descripcion' => $producto->getDescripcion(), 'precio' => $producto->getPrecio());
        
$this->insert($data);
    }

Controlador
Código PHP:
public function nuevoAction(){
   
$params $this->getRequest()->getPost();
   
$producto = new My_Producto($params['nombre'],$params['descripcion'],$params['precio'] );
   
$modeloProducto = new Application_Model_DbTable_Productos;             
   
$modeloProducto->save($producto);
 } 

OPCION[3] Desde el Controlador instancio el objeto Producto y desde un metodo del producto llamo al modelo para hacer la persistencia

En este caso encuentro dos variantes,
A) EL metodo salvarProducto() de la clase My_Producto ya tiene definida la clase sobre la que hara la persistencia
B) El metodo salvarProductoDos() de la clase My_Producto recibe la clase sobre la que se hara la persistencia cumpliendo siempre con una Interfaz

Clase del Modelo (Ubicada en library/My/Producto/DataSource/ZendDB.php
Código PHP:
class My_Producto_DataSource_ZendDB extends Zend_Db_Table_Abstract implements My_Producto_DataSource_Interfaz
{
    protected 
$_name 'productos';
     public function 
save($nombre,$descripcion,$precio){  
        
$data = array('nombre'=> $nombre'descripcion' => $descripcion'precio' => $precio);
        
$this->insert($data);
    }

Clase Producto
Código PHP:

class My_Producto{

   private 
$_nombre;
   private 
$_descripcion;
   private 
$_precio;

 public function 
__construct($nombre null$descripcion null,  $precionull){
   
$this->_nombre $nombre;
   
$this->_descripcion $descripcion;
   
$this->_precio $precio;
 }

 public function 
salvarProducto(){
   
$modeloProducto = new Application_Model_DbTable_Productos;             
   
$modeloProducto->save($this->getNombre(),$this->getDescripcion(),$this->getPrecio());
 }
 
 public function 
salvarProductoDos(My_Producto_DataSource_Interfaz $dataSource ){ 
   
$dataSource->save($this->getNombre(),$this->getDescripcion(),$this->getPrecio());
 }


Controlador
Código PHP:
public function nuevoAction(){
   
$params $this->getRequest()->getPost();
   
$producto = new My_Producto($params['nombre'],$params['descripcion'],$params['precio'] );
   
$producto->salvarProducto();
   
//O...
   
$producto->salvarProductoDos(new Application_Model_DbTable_Productos);
 } 
Espero puedan brindarme a traves de sus conociemientos y expereciencia cual creen que seria la forma mas correcta o bien si ninguna de estas formas es correcta cual seria.
Muchas gracias.
  #2 (permalink)  
Antiguo 08/03/2011, 14:56
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 5 meses
Puntos: 2135
Respuesta: Zend - MVC - Duda Persistencia / Modelo

A mi parecer la opción más limpia es la 2, aunque te recomendaría usar un DataMapper

¿Que es un Data Mapper?

Precisamente es una capa entre el controlador y tu capa de persistencia, a la que le alimentas objetos y te regresa objetos, es la opción más limpia a mi parecer y así no expones código de tu capa de persistencia al controlador y esta, esta totalmente contenida.

Lo ideal en este caso es que crees un objeto en tu controlador (no importa el input ya sea un request, etc.) Y pases este objeto a tu capa, que se encarga de llamar a la persistencia y salvar el objeto (esto hace que puedas implementar cualquier ORM de una forma más sencilla).

Un ejemplo:
Código PHP:
Ver original
  1. public function fooAction()
  2. {
  3.        $aPostData = $this->getRequest()->getPost();
  4.        $Producto = new Model_Producto();
  5.        $Producto->setTitle($aPostData['title'])
  6.                        ->setDescription($aPostData['description']);
  7.  
  8.        $ProductoMapper = new Application_Model_Mapper_Productos();
  9.        $ProductoMapper->saveProducto($Producto);
  10. }

Mapper:
Código PHP:
Ver original
  1. public function saveProducto(Model_Producto $Producto)
  2. {
  3.          $DbTable = new Application_Model_DbTable_Producto();
  4.          $aData = array(
  5.                  'title' => $Producto->getTitle(),
  6.                  'description' => $Producto->getDescription()
  7.          );
  8.  
  9.          $DbTable->insert($aData);
  10. }

Puede parecer más código (y lo es) pero depende mucho como abstraigas, igual puedes crear un Base_Model, Factory, etc. La idea es abstraer el paso de datos entre tu controller y tu capa ORM.

Saludos.
  #3 (permalink)  
Antiguo 08/03/2011, 16:13
 
Fecha de Ingreso: diciembre-2010
Mensajes: 13
Antigüedad: 13 años, 11 meses
Puntos: 0
Respuesta: Zend - MVC - Duda Persistencia / Modelo

GatorV, te agradezco la ayuda, vale muchisimo para mi. Voy a aplicar datamapper a mis proyectos, siguiendo el lineamiento que me indicas.

Estuve buscando el concepto de Base_Model y factory aplicado sobre el modelo y datamapper pero no encontré mucho, si sos tan amable podrías ampliarme algo del tema o darme alguna referencia para estudiarlo bien.

Por otro lado consultarte si recomiendas por tu experiencia usar ORM como Doctrine o propel, o con Zend_Db_Table y demas clases de Zend alcanza.
  #4 (permalink)  
Antiguo 08/03/2011, 16:21
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 5 meses
Puntos: 2135
Respuesta: Zend - MVC - Duda Persistencia / Modelo

Zend_Db_Table no es un ORM, es una solución simple implementando el patrón Table Gateway, si quieres usar un ORM, Doctrine es el indicado, Propel hasta donde conozco es una librería tipo PDO que usaba Doctrine, y que ahora ya se mudaron a usar PDO directamente.

Lo que me refiero es usar un patrón como factory para crear tus objetos de una forma sencilla (y así optimizar códigos) por ejemplo:
Código PHP:
Ver original
  1. class Model_Factory
  2. {
  3.         pubic static function factory($sName, $aData = array())
  4.         {
  5.                   $sModelName = "Model_$sName";
  6.                   $Model = new $sModelName();
  7.  
  8.                   foreach ($aData as $sProperty => $sValue) {
  9.                           $sSetter = 'set' . ucfirst($sProperty);
  10.                           $Model->$sSetter($sValue);
  11.                   }
  12.  
  13.                   return $Model;
  14.         }
  15. }

Y así podrías hacer algo así:
Código PHP:
Ver original
  1. public function fooAction()
  2. {
  3.           $aValues = $this->getRequest()->getPost();
  4.           // suponiendo que ya fueron validados
  5.           $Model = Model_Factory::factory('Productos', $aValues);
  6. }

El otro es para por ejemplo implementar funciones comunes a tus objetos que necesites, para poder pasarlos a tu ORM.

Saludos.
  #5 (permalink)  
Antiguo 08/03/2011, 16:44
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 10 meses
Puntos: 845
Respuesta: Zend - MVC - Duda Persistencia / Modelo

Que krikis,

En el quickstart tenes un mapper basico, te puede ayudar a que te ordenes un poco.
Con respecto a si un ORM o Zend_Db_Table, depende del proyecto, para casos simples, donde tu domain model mapea igual que la bbdd y no tiene relaciones complejas te va a servir, ahora si no mapea igual y tenes un grafo de relaciones complejo, Zend_Db_Table se queda corto y te sugiero al igual que GatorV Doctrine y si es posible la version 2(una sal , la contra PHP 5.3+).

@GatorV, Propel es un ORM al igual que doctrine, es mas era la competencia directa, hasta ahora que a tirado la toalla y han decido para la version 2 ser una capa arriba de Doctrine 2.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #6 (permalink)  
Antiguo 08/03/2011, 16:55
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 5 meses
Puntos: 2135
Respuesta: Zend - MVC - Duda Persistencia / Modelo

Cierto algo así sabia de Propel, que había sido descartado para mejor usar Doctrine como tal
  #7 (permalink)  
Antiguo 08/03/2011, 17:21
 
Fecha de Ingreso: diciembre-2010
Mensajes: 13
Antigüedad: 13 años, 11 meses
Puntos: 0
Respuesta: Zend - MVC - Duda Persistencia / Modelo

Muchas gracias. Ahora incluso me queda claro el datamapper del quickStart de Zend.

Saludos!

Etiquetas: frameworks-y-php-orientado-a-objetos, modelo, mvc, persistencia
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:13.