Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

Clase modelo.(MVC) Conexión a base de datos.

Estas en el tema de Clase modelo.(MVC) Conexión a base de datos. en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Hola Siguiendo el patrón MVC tengo clases que interacturan únicamente con la base de datos. Actualmente en el constructor de dichas clases creo la conexión ...
  #1 (permalink)  
Antiguo 12/10/2011, 06:27
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Clase modelo.(MVC) Conexión a base de datos.

Hola

Siguiendo el patrón MVC tengo clases que interacturan únicamente con la base de datos.
Actualmente en el constructor de dichas clases creo la conexión con la base de datos de este modo:
Código PHP:
public function __construct(){
        
$db_pass="ss";
        
$db_name="aa";
        
$db_host="aa.com";

        
mysql_connect($db_host,$db_name,$db_pass);
        
mysql_select_db($db_name);    
    } 
Y esto me da algunos problemas a la hora de trabajar con varias conexiones a bases de datos diferentes dentro de bucles.

¿Cómo se suele realizar la conexión de forma habitual? Tal vez no sea en el constructor. ¿no?
Pero de no ser así, ¿no sería un poco absurdo llamar a la función de conectar en TODOS los métodos de la clase?

Un saludo.
  #2 (permalink)  
Antiguo 12/10/2011, 07:09
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Lo que no tiene sentido es hardcodear los datos de conexión, porque no lo pasas por parámetro ?, igual te sugiero que utilices PDO, cada vez veo ese mysql_connect quedo .

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #3 (permalink)  
Antiguo 12/10/2011, 08:10
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Exacto, este es uno de los perfectos ejemplos de como PDO + patrón registry puede servir para lo que deseas, y porque Singleton no es aconsejable para Bases de Datos:
Código PHP:
Ver original
  1. $db1 = new PDO(/**/);
  2. $db2 = new PDO(/**/);
  3. $db3 = new PDO(/**/);
  4.  
  5. Registry::set('db1', $db1);
  6. Registry::set('db2', $db2);
  7. Registry::set('db3', $db3);
  8.  
  9. /** Mas adelante **/
  10. for (/** **/) {
  11.       $db1 = Registry::get('db1');
  12.       $db1->execute(/**/);
  13.  
  14.       $db2 = Registry::get('db2');
  15.       //etc.
  16. }
  #4 (permalink)  
Antiguo 12/10/2011, 08:40
Avatar de Webstudio
Colaborador
 
Fecha de Ingreso: noviembre-2001
Ubicación: 127.0.0.1
Mensajes: 3.499
Antigüedad: 22 años, 5 meses
Puntos: 69
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

IMAC, como estás...
Si vos hacés que CADA clase que trabaja con base de datos, tenga los datos de conexión, te vas a volver loco a la hora de cambiarlos de lugar. Yo te recomiendo hacer algo asi:

Código PHP:
<?php
class DB
{
    protected 
$_config = array();
    protected 
$_conn null;
    protected 
$_stmt null;

    public function 
__construct($config)
    {
        
$this->_config $config;
    }

    public function 
connect()
    {
        
$this->_conn = new PDO(
            
$this->getConnString(),
            
$this->_config['user'],
            
$this->_config['password']);
    }

    public function 
isConnected()
    {
        return 
$this->_conn != null;
    }

    public function 
getConn()
    {
        return 
$this->_conn;
    }

    public function 
query($query)
    {
        
$this->_stmt $this->_conn->query($query);
    }
    
    
/** etc, etc, etc, acá implementás los métodos que te sean útiles 
        O directamente podés utilizar los objetos que te ofrece PDO */
}

class 
MySQLDB extends DB
{
    public function 
getConnString()
    {
        return 
'mysql:'
              
.'host='.$this->_config['host'].';'
              
.'dbname='.$this->_config['dbname'];
    }
}

class 
SQLiteDB extends DB
{
    public function 
getConnString()
    {
        return 
'sqlite:'.$this->_config['file'];
    }
}
Con esto, ya unificaste en un par de clases todo lo que es la creación de nuevas conexiones, incluso de distintos tipos de conexiones. Ya podés reutilizar este código en otros lados :

Código PHP:
/** Conexión 1 */
$config get_configuracion(); // Esto saldrá de algún lado.
$mysql  = new MySQLDB($config);


/** Conexión 2 */
$mysql2 = new MySQLDB(array(
    
'host'      => '127.0.0.1',
    
'user'      => 'webstudio',
    
'password'  => 'nosedicenlospasswords',
    
'dbname'    => 'nilosnombresdedb',
));

/** Conexión 3 - otro motor de base de datos */
$sqlite = new SQLiteDB(array('/var/www/foros/usuarios.sqlite')); 
Entonces, si tenés distintos tipos de clases que interactúan con distintos tipos de datos en tu sistema, pasando la instancia específica, ya podés usar la base de datos sin tener que preocuparte, por qué tipo es, ni reescribiendo código.

Código PHP:
class Model
{
    protected 
$_db null;

    public function 
__construct(DB $db)
    {
        
$this->setDb($db));
    }

    public function 
setDb(DB $db)
    {
        
$this->_db $db;
    }
}

class 
Product extends Model
{
    public function 
getProducts()
    {
        
$conn $this->_db->getConn();
        return 
$conn->query('SELECT * from products');
    }
}


class 
User extends Model
{
    public function 
getById($id)
    {
        
$conn $this->_db->getConn();
        
$query $conn->prepare('SELECT blabla FROM users WHERE id = :id');

        return 
$query->execute(array(':id' => $id));
    }
}

$users = new User($sqlite);
$user $users->getById(5);

$products = new Products($mysql);
$all $products->getProducts(); 
Como te darás cuenta, al estar utilizando PDO, casi que no te importa ahora qué tipo de base de datos estás utilizando en tus objetos, simplemente funcionan porque comparten la misma API.

Saludos y espero que te sirva.
__________________
Tutoriales Photoshop | Web-Studio.com.ar
Artículos PHP | ZonaPHP.com
  #5 (permalink)  
Antiguo 12/10/2011, 15:04
Avatar de Webstudio
Colaborador
 
Fecha de Ingreso: noviembre-2001
Ubicación: 127.0.0.1
Mensajes: 3.499
Antigüedad: 22 años, 5 meses
Puntos: 69
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Quizás es hora que comience a tomar todos estos códigos y escribir un par de tutoriales en ZonaPHP.com no ?
__________________
Tutoriales Photoshop | Web-Studio.com.ar
Artículos PHP | ZonaPHP.com
  #6 (permalink)  
Antiguo 12/10/2011, 15:11
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Puede ser, lo que expones de Dependendy Injection es lo que muchos programadores necesitan aprender.
  #7 (permalink)  
Antiguo 12/10/2011, 15:39
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Buf, no se Webstudio, lo que me comentas me aprece demasiado lio para lo que voy a llevar a cabo.

No tengo pensado cambiar de base de datos.

Simplemente quería saber cómo se pueden hacer las conexiones de modo que no se interrumpan unas a otras.

La verdad es que he estado ojeando un poco el PDO que comentáis pero no acabo de entenderlo muy bien.
Tal vez tengo que mirarlo algo más a fondo y no solo por encima...
  #8 (permalink)  
Antiguo 12/10/2011, 16:18
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Puede que sea demasiado lio inicial, pero a la larga (haciendo testing y más) veras las ventajas.

Saludos.
  #9 (permalink)  
Antiguo 20/06/2012, 04:40
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Buenas Webstudio,

Estoy intentando implementar el código que publicaste en su día y estoy teniendo un problemilla.
Bueno, antes de nada, decir que no conectas con la base de datos por ningún lado, faltaría el $this->_db->connect();

Y después, que al hacer el getProducts(), por ejemplo, lo que me devuelve no es un array con la consulta ejecutada, sino más bien esto:
PDOStatement Object ( [queryString] => SELECT * from prueba )

¿A qué se debe?
¿Cómo ejecuto la sentencia sql?

Gracias.
  #10 (permalink)  
Antiguo 20/06/2012, 05:04
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Vale, acabo de ver que si se itera sobre el mismo con un foreach si que funciona:

Código PHP:
foreach ( $all as $row){
    echo 
$row["nombre"];

Pero no funciona un
Código PHP:
print_r($products->getProducts()) 
Habría que hacer:
Código PHP:
print_r($products->getProducts()->fetchAll()); 
  #11 (permalink)  
Antiguo 20/06/2012, 09:22
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Lo que pasa es que al usar PDO te devuelve un PDOStatement, deberías de ver en el Manual como funciona el PDOStatement y los beneficios que tiene.

Saludos.
  #12 (permalink)  
Antiguo 20/06/2012, 10:09
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Eso estoy intentando averiguar GatorV :)
Por ahora estoy basándome en el ejemplo de Webstudio y he planteado las siguiente clases dentro de mi carpeta "model" que funcionará como modelo en el esquema MVC.

Databaseconfig.php con la configuración de la base de datos y una única función get_configuracion
DB.php que contiene la clase DB que ha publicado Webstudio
Model.php que contiene la case Model que ha publicado Webstudio
MySQLDB.php que contiene la clase MySQLDB que ha publicado Webstudio

Y posteriormente irían las clases correspondientes a cada objeto o clase creada en el controlador, como por ejemplo ( vídeo, usuario, ciudad...) etc.
Que contendrán funciones similares a la de getProducts publicada por Webstudio.

¿Es esta organización correcta?

Un saludo y gracias.
  #13 (permalink)  
Antiguo 20/06/2012, 10:24
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Me han recomendado usar algunos ORM como propelorm (http://www.propelorm.org/) o Doctrine (http://www.doctrine-project.org/).
¿Es esto compatible con OPD? ¿Cuál es mejor?
  #14 (permalink)  
Antiguo 20/06/2012, 10:36
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

No recuerdo de Propel, pero Doctrine sí está basado en DBAL, que dentro usa PDO.

Respecto a cual es mejor, yo creo que Doctrine es mejor, pero ya hablar de un ORM es otro boleto, no es un simple layer de acceso a tu BDD, es trabajar con un esquema totalmente diferente y dejar al ORM persistir los datos a tu BDD.
  #15 (permalink)  
Antiguo 20/06/2012, 10:40
Avatar de Ribon  
Fecha de Ingreso: septiembre-2010
Ubicación: El firmamento
Mensajes: 487
Antigüedad: 13 años, 7 meses
Puntos: 91
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Webstudio, solo una sugerencia xD!

La clase DB debería ser abstract y tener un método abstracto llamado getConnString.

Solo como acotación de diseño :P, ya que la instanciación de DB no debería estar permitida sin implementar ese método.

Saludos :X
__________________
Utilice el Highlight para mostrar código, mis ojos se lo agradecerán :)
qué es esto? :O -> http://i48.tinypic.com/5x3kzs.png
Ya sabes :)
  #16 (permalink)  
Antiguo 19/07/2012, 10:57
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Buenas de nuevo...

Estoy teniendo algún problemilla. Si imprimo el contenido de $query una vez echo el prepare, me sale esto:
Código PHP:
PDOStatement Object ( [queryString] => SELECT firstName FROM user 
Pero una vez que hago el execute lo vuelvo a imprimir y solamente me sale "1", cuando me debería de salir un array con los datos... ¿Qué puede estar pasando?

Para que veáis todo el código os lo dejo aquí:

/model/DatabaseConfig.php
/model/DB.php
/model/Model.php
/model/MySQLDB.php
/model/User.php

View/index.php

Seguramente sea una tontería...
La conexión con la base de datos,( $this->_db->connect();) la puse directamente sobre el modelo User.php, no se donde la pondríais vosotros... en estos ejemplos que habéis puesto no aparece por ningún sitio.

El método isConnected me devuelve 1, de modo que por lo visto conecta con la BD correctamente...

Un saludo.
  #17 (permalink)  
Antiguo 19/07/2012, 11:13
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Vale, ya lo he encontrado...
Estaba usando
Código PHP:
        $query $conn->prepare('SELECT * FROM users'); 

        return 
$query->execute(); 
En lugar de
Código PHP:
        return $conn->query('SELECT * from users'); 
¿Cuál es la diferencia entre ambos modos de hacerlo?
  #18 (permalink)  
Antiguo 19/07/2012, 12:50
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Pues ambos te regresan un PDOStatment object, realmente lo que hace query es un prepare / execute, o sea es un "atajo" para hacer en la misma llamada el prepare y execute.
  #19 (permalink)  
Antiguo 19/07/2012, 13:24
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

He leido por ahí que prepare también evita SQL injections y query no a la hora de usar parámetros.
  #20 (permalink)  
Antiguo 19/07/2012, 13:30
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Así es, y no es que te proteja, si no que al usar el prepared statement tienes más control sobre los parámetros que acepta tu query.
  #21 (permalink)  
Antiguo 19/07/2012, 14:10
Avatar de IMAC/  
Fecha de Ingreso: octubre-2005
Mensajes: 738
Antigüedad: 18 años, 6 meses
Puntos: 14
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

¿A qué te refieres GatorV?
Pensé que usando PDO uno se protegía contra este tipo de inyecciones SQL.
  #22 (permalink)  
Antiguo 19/07/2012, 14:49
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Clase modelo.(MVC) Conexión a base de datos.

Sí, pero solo si usas Prepared Statements, si armas Querys concatenando strings, no hay ningún beneficio.

Saludos.

Etiquetas: clase
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 22:15.