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

Mi primer código POO - Dudas

Estas en el tema de Mi primer código POO - Dudas en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Aupa, He empezado a meterme con la POO y después de leer manuales he realizado mi primer código que lo "único" que hace es listar ...
  #1 (permalink)  
Antiguo 10/12/2012, 10:09
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Mi primer código POO - Dudas

Aupa,
He empezado a meterme con la POO y después de leer manuales he realizado mi primer código que lo "único" que hace es listar la tabla de usuarios y me han surgido las primeras dudas.

He creado dos clases. La primera conexión que hace la conexion, ejecutar, limpiar y cierra.
Código PHP:
class conexion
{
  private 
$servidor;
  private 
$usuario;
  private 
$password;
  private 
$bd;
  private 
$database;
  
  public function 
__construct($servidor"localhost"$usuario "root"$password =   ""$bd "abm")
  {
      
$this->servidor=$servidor;
      
$this->usuario=$usuario;
      
$this->password=$password;
      
$this->bd=$bd;
      
$this->database = new mysqli($servidor$usuario$password$bd);
      if (
$this->database->connect_error) {
          die(
"Error (" $this->database->connect_errno ") "$this->database->connect_error);
      }
  }
  
  public function 
ejecutar($sql// ejecuta consulta
  
{
      return 
mysqli_query($this->database,$sql);        
  }    
  public function 
limpiar() // libera la consulta
  
{
      
mysql_free_result($this->database);
  }
  public function 
cerrar() // cierra la conexion
  
{
      
$this->database->Close();
  }            

La segunda usuario hereda de la primera y lista los usuarios
Código PHP:
class usuario extends conexion
{
  public function 
__construct()
  {
    
parent::__construct();    
  }
  
  public function 
listar()
  {
    
$sql="select * from clientes";
    
$result=parent::ejecutar($sql);
    return 
$result;
    
parent::limpiar();
  }  

Y donde se crea las clases:
Código PHP:
$cliente=new usuario();
$result=$cliente->listar();
  if(
$result) {
      echo 
$result->num_rows."<br />";
      if (
$result->num_rows!=0)
      {
          while (
$rowCam $result->fetch_row())
          {
              echo 
$rowCam[1]."<br />";
          }
      }
  }
  else
      echo 
"Error SQL";    
$cliente->cerrar(); 
¿Veís todo bien? Los resultados si los muestra pero no sé si lo he hecho de la mejor forma.

Y una duda que me ha surgido. Si creo en esta misma página otra clase que hereda de conexion se me abriria dos conexiones en la misma página (la nueva y la de usuario). Es mejor tener la clases que no hereden de conexion o como es la forma más obtima de hacerlo.

Muchas gracias de antemano
  #2 (permalink)  
Antiguo 10/12/2012, 10:54
Avatar de cluster28  
Fecha de Ingreso: enero-2008
Ubicación: Donostia - San Sebastián
Mensajes: 756
Antigüedad: 16 años, 4 meses
Puntos: 32
Respuesta: Mi primer código POO - Dudas

Yo particularmente no heredaría Usuario de conexion, porque un Usuario no es una conexión.

En todo caso utilizaría la conexión dentro de Usuario, $conn = new conexion().....

Esto es la composición frente a la herencia. La herencia es mejor usarla cuando algo sea algo de su padre.

Ejemplo:

Yo he creado una clase "Bd", una "EntidadBd" y otra "Usuario".

Usuario es hija de EntidadBd y EntidadBd usa Bd dentro de ella misma. Usuario también puede usar Bd.

De esta manera se puede abstraer todo el acceso a la base de datos de la entidad que la necesite o también usarla en un determinado script, función o lo que sea.

Si desarrollas bien EntidadBd con acciones muy comunes a las entidades de la base de datos (guardar, cargar, eliminar, etc...), la mayoría de las funcionalidades de las nuevas clases hijas ya estarán en EntidadBd, por lo que aumentas la velocidad de desarrollo.

La idea de EntidadBd y derivar de ella es para hacer un patrón Active Record

Para la clase Bd uso el patrón Singleton De esta manera sólo tendrás una conexión a la base de datos.

Pregunta todo lo que quieras ya este tema es bastante subjetivo en cada uno.
  #3 (permalink)  
Antiguo 10/12/2012, 15:29
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Muchas gracias cluster28!!!
Entiendo ahora la diferencia entre composición frente a la herencia. Usuario no puede heredar de conexion.

Pero una cosita que no entiendo en tu ejemplo.
- En la clase EntidadBd que métodos habria? Obtener resultados y ejecutar sql? Y Enridad BD sería una herencia de conexión no?
- Y en la clase Usuario en el contructor abriria el objeto EntidadBd?

Gracias por las respuestas!!
  #4 (permalink)  
Antiguo 10/12/2012, 18:37
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: Mi primer código POO - Dudas

No, de hecho es al contrario, Usuario hereda de EntidadDb, ya que un Usuario es una EntidadDB, y EntidadDB es la que usa la conexión.

¿Que métodos? Pues lo básico, crear, salvar, borrar, etc. Es el principio de lo que se conoce ActiveRecord.

Saludos.
  #5 (permalink)  
Antiguo 11/12/2012, 02:18
Avatar de cluster28  
Fecha de Ingreso: enero-2008
Ubicación: Donostia - San Sebastián
Mensajes: 756
Antigüedad: 16 años, 4 meses
Puntos: 32
Respuesta: Mi primer código POO - Dudas

Cita:
Iniciado por GatorV Ver Mensaje
No, de hecho es al contrario, Usuario hereda de EntidadDb, ya que un Usuario es una EntidadDB, y EntidadDB es la que usa la conexión.

¿Que métodos? Pues lo básico, crear, salvar, borrar, etc. Es el principio de lo que se conoce ActiveRecord.

Saludos.
Eso es.

La idea es crear un clase que comunique/trabaje con las base de datos. Que haga de puente entre el/los objeto/s, los scripts y la base de datos. Ahí puedes crear los métodos que quieras o que necesites. Cosas básicas que se hacen sobre una base de datos.

Teniendo una clase base de las "entidades" (registros de tablas) conseguimos que las funciones comunes de cualquier entidad, tal como dice GatorV, crear, salvar, borrar, etc. estén ya implementadas en EntidadBd y sólo quedaría derivarla en las entidades que queramos. En este caso Usuario. Si un día necesitas trabajar con Productos, pues sólo tienes que crear la clase derivada de EntidadBd y todas funcionalidades comunes ya las tienes.

En Bd por ejemplo puede haber estos métodos:

- ejecutarSQL()
- iniciarTransaccion()
- commitTransaccion()
- rollbackTransaccion()
- isInTransaccion()
- getTablas()
- getTotalRegistrosDeTabla()
- getCamposDeTabla()

En EntidadBd estos otros:

- guardar()
- eliminar()
- getArrayDeDatos()
- clonar()

En Usuario métodos como:

- login()
- darDeAlta()

Luego las irás completando según vayas necesitando métodos.
  #6 (permalink)  
Antiguo 11/12/2012, 03:41
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Lo primero muchas gracias a los dos por vuestra ayuda. Me estaís ayudando muchísimo en este tema que para mi es todo un mundo nuevo. Gracias!!

Después de vuestros comentarios mi código ha quedado de la siguiente forma:

La clase conexión que crea la conexion, la envia y la cierra
Código PHP:
class conexion
{
  private 
$servidor;
  private 
$usuario;
  private 
$password;
  private 
$bd;
  private 
$database;
  
  public function 
__construct($servidor"localhost"$usuario "root"$password =   ""$bd "abm")
  {
    
$this->servidor=$servidor;
    
$this->usuario=$usuario;
    
$this->password=$password;
    
$this->bd=$bd;
    
$this->database = new mysqli($servidor$usuario$password$bd);
    if (
$this->database->connect_error) {
        die(
"Error (" $this->database->connect_errno ") "$this->database->connect_error);
    }
  }    
  
  public function 
getConexion()
  {
    return 
$this->database;
  }  
  public function 
close() 
  {
    
$this->database->close();
  }      

La clase query que ejecuta y limpia las consultas. Aquí ire metiendo más métodos.
Código PHP:
class query
{
  public function 
__construct()
  {
    
$this->pconeccion= new conexion();
  }
  public function 
__destruct()
  {
    
$this->pconeccion->close();
  }   
  
  public function 
ejecutar($sql// ejecuta consulta
  
{
    return 
mysqli_query($this->pconeccion->getConexion(),$sql);          
  }
  public function 
limpiar() // libera la consulta
  
{
    
mysql_free_result($this->pconeccion->getConexion());
  } 
             

Y la clase usuario, que es una clase que hereda de query
Código PHP:
class usuario extends query
{
  public function 
__construct()
  {
       
parent::__construct(); 
  }
  public function 
__destruct()
  {
       
parent::__destruct(); 
  }  
  
  public function 
listar()
  {
    
$sql="SELECT * FROM clientes";
    
$result=parent::ejecutar($sql);
    return 
$result;
    
parent::limpiar();
  }     

Lo veís mejor ahora.

Y mis dudas:
Es correcto crear la conexión desde el constructor? Y cerrar la conexión desde el destructor?

Si creo otra clase productos que tb hereda de query (constructor y destructor igual que usuario) y estoy trabajando a la vez con usuarios y productos se me crearian dos conexiones a la BBDD. Eso no sería correcto no?

Lo siento por mis dudas pero soy muyyy novato.
  #7 (permalink)  
Antiguo 11/12/2012, 04:07
Avatar de cluster28  
Fecha de Ingreso: enero-2008
Ubicación: Donostia - San Sebastián
Mensajes: 756
Antigüedad: 16 años, 4 meses
Puntos: 32
Respuesta: Mi primer código POO - Dudas

Puedes hacerlo como mejor te venga. Hay que intentar crear clases de "cosas" y que con sólo ver su nombre sepas lo que puedes encontrar en ella. Por ejemplo la clase query no queda muy claro lo que es. Bueno si, da interacción con la base de datos, pero el nombre no queda del todo bien. BdHandler que te parece?

De todos modos tanto conexion como query son cosas que se hacen sobre una base de datos por lo que yo no haría dos clases distintas a no ser que tengas una razón sólida. Yo haría una sola clase, Bd

La clase Usuario está bien salvo el método listar(), debería ser así

Código PHP:
public function listar()
  {
    
$sql="SELECT * FROM clientes";
    
$result=$this->ejecutar($sql);
    
$this->limpiar();
    return 
$result;
  } 
De todos modos aquí se trata de que cada uno cree modelos de datos, patrones y clases de las necesidades que tenga. Aquí no hay pócima secreta. Sólo hace falta tiempo. Yo sólo llevo tres años en esto y cuando miro código del principio flipo de las cosas tan complicadas que hacía pudiéndolas hacer más sencillas.

Yo aprendí mucho de conceptos POO con un libro de Java. En concreto Piensa en Java

Cita:
Si creo otra clase productos que tb hereda de query (constructor y destructor igual que usuario) y estoy trabajando a la vez con usuarios y productos se me crearian dos conexiones a la BBDD. Eso no sería correcto no?
En esto la verdad es que no lo se del todo. Al usar el patrón singleton yo sólo uso una instancia y no he salseado mucho más.
  #8 (permalink)  
Antiguo 11/12/2012, 05:19
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Ahora me has matado cluster28!!! Parece que no te había entendido bien en tus mensaje jejeje

A ver si ahora lo entiendo bien:

Creo una clase conexion donde se va a gestionar la conexion,cierre y la ejecución de sql. Y hay añadiré los métodos que vaya necesitando de la BBDD.

Y luego creo una clase usuarios que NO hereda de conexion. Simplemente llama a conexion no? Y si voy creando nuevas clases pues lo mismo.

Sobre lo de la conexión a la BBDD que es mejor: Abrir una conexión al principio de la página y cerrarla al final o por el contrario ir abrir conexion ->Hacer SQL -> Cerrar Conexión y así con todas las sentencias que existan en la página. Es decir abrir una y usarla para todas las sentencias o ir abriendo y cerrando conexiones.

Un saludo y de nuevo gracias!!!!!!

Edito para añadir un enlace en el que me habia basado:
http://www.jc-mouse.net/php/autentic...on-mysql-y-poo

Última edición por Agrey; 11/12/2012 a las 05:20 Razón: Edito para añadir enlace
  #9 (permalink)  
Antiguo 11/12/2012, 06:11
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: Mi primer código POO - Dudas

Un clase debería resolver un único problema, que intentas modelar en la clase Query ?, en AR los modelos extienden de una clase base(por lo general se llama Record) que les da la funcionalidad básica(load, hydrate, refresh, save, etc...).

Sobre las conexiones, PHP cuando termina de ejecutarse el script cierra automáticamente todas las conexiones, en lo que deberías preocuparte es en no abrirlas innecesariamente, para esto te sugiero una propiedad estática en la clase base.

En relación al código que muestras, estas hardcodeando las dependencias, imagínate que quieres utilizar otra conexión para la clase Query, si es requerida la dependencia para el funcionamiento de la clase deberías inyectarla vía constructor.
Código PHP:
Ver original
  1. class Query
  2. {
  3.     ...
  4.     public function __construct(Connection $conn)
  5.     {
  6.         $this->conn = $conn;
  7.     }
  8.     ...
  9. }

Y bueno sobre Singleton..., les sugiero que hagan una búsqueda en el foro o google, es algo que deberían evitar http://blogs.msdn.com/b/scottdensmor...25/140827.aspx
__________________
http://es.phptherightway.com/
thats us riders :)
  #10 (permalink)  
Antiguo 11/12/2012, 06:42
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Gracias masterpuppet por tu respuesta pero no entiendo muy bien lo que has expuesto. Tengo nivel O ;)

Despues de leer manuale me he basado en este ejemplo
http://www.jc-mouse.net/php/autentic...on-mysql-y-poo
  #11 (permalink)  
Antiguo 11/12/2012, 08:10
Avatar de Genetix  
Fecha de Ingreso: febrero-2002
Ubicación: Lima - Perú
Mensajes: 1.600
Antigüedad: 22 años, 2 meses
Puntos: 45
Respuesta: Mi primer código POO - Dudas

Adicionalmente a lo que te menciona masterpuppet, puedes echarle un vistazo a los conceptos SOLID
http://www.genbetadev.com/paradigmas...seno-de-clases

Saludos!
__________________
"El conocimiento nos hace responsables."
twitter: @benjamingb
blog personal: http://codigolinea.com
ZF Manual en español http://manual.zfdes.com
  #12 (permalink)  
Antiguo 11/12/2012, 08:24
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Gracias Genetix por la info.
  #13 (permalink)  
Antiguo 11/12/2012, 09:09
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Buenas!!!
Sigue aquí peleándome con mis primeras clases y como dice cluster28 Aquí no hay pócima secreta. Sólo hace falta tiempo

He modificado mis clases y el objetivo es obtener un listado de todos los usuarios y por cada usuario obtener el número de pedidos.

Tengo la clase conexion, donde se conecta se ejecuta la sql y se cierra la conexion
Código PHP:
class conexion
{
  private 
$servidor;
  private 
$usuario;
  private 
$password;
  private 
$bd;
  private 
$database;
  
  public function 
__construct($servidor"localhost"$usuario "root"$password =   ""$bd "abm")
  {
      
$this->servidor=$servidor;
      
$this->usuario=$usuario;
      
$this->password=$password;
      
$this->bd=$bd;
      
$this->database = new mysqli($servidor$usuario$password$bd);
      if (
$this->database->connect_error) {
          die(
"Error (" $this->database->connect_errno ") "$this->database->connect_error);
      }
  }
  public function 
ejecutar($sql// ejecuta consulta
  
{
    return 
mysqli_query($this->database,$sql);        
  }    
  public function 
limpiar() // libera la consulta
  
{
      
mysqli_free_result($this->database);
  }
  public function 
cerrar() // cierra la conexion
  
{
    
$this->database->Close();
  }            

Luego otra clase usuario que lista los usuarios

Código PHP:
class usuario
{
  public function 
__construct()
  {
         
  }
  public function 
listar()
  {
    
$obj_cliente=new conexion();
    
$sql="select * from clientes";
    
$result=$obj_cliente->ejecutar($sql);
    return 
$result;
    
$obj_cliente->limpiar();
    
$obj_cliente->cerrar();
  }   

y una clase productos que obtiene los productos de un determinado cliente
Código PHP:
class productos
{
  public function 
__construct()
  {
         
  } 
  public function 
listar_productos($id)
  {
    
$sql="select * from productos WHERE id='".$id."'"
    
$obj_cliente=new conexion();    
        
$result=$obj_cliente->ejecutar($sql);
    return 
$result;    
    
$obj_cliente->limpiar();
    
$obj_cliente->cerrar();        
  }     

El código php que llama a los objetos:
Código PHP:
        $cliente=new usuario();
        
$result=$cliente->listar();
          if(
$result) {
              if (
$result->num_rows!=0)
              {
                 
$productos=new productos();                  
                  while (
$rowCam $result->fetch_row())
                  {
                      echo 
$rowCam[1]."-";
                      
$prod=$productos->listar_productos($rowCam[1]);
                      echo 
$prod->num_rows."<br />";
                  }
              }
          } 
No me da ningún error pero no veo muy claro que lo esté haciendo bien. Eso de estar llamando constantemente new conexion() desde los métodos no lo veo muy profesional jeje

Es abusar pero ... ¿como sería esto?
Un saludo y desde ya muchas gracias!!!
  #14 (permalink)  
Antiguo 11/12/2012, 09:42
Avatar de Genetix  
Fecha de Ingreso: febrero-2002
Ubicación: Lima - Perú
Mensajes: 1.600
Antigüedad: 22 años, 2 meses
Puntos: 45
Respuesta: Mi primer código POO - Dudas

Cita:
Eso de estar llamando constantemente new conexion() desde los métodos no lo veo muy profesional jeje
Efectivamente no lo es :)
Te recomedaria que le eches un vistazo a tema de patrones y lo que ya te mencione, a los principios SOLID, se que para algunos puede ser tedioso leerlos, pero si no entiendes muy bien de que se trata y como se aplica vas a seguir cayendo en el mimo error.

Saludos!
__________________
"El conocimiento nos hace responsables."
twitter: @benjamingb
blog personal: http://codigolinea.com
ZF Manual en español http://manual.zfdes.com
  #15 (permalink)  
Antiguo 11/12/2012, 09:55
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: Mi primer código POO - Dudas

Exacto como ya te dijo @masterpuppet, debes de buscar usar un patrón que resuelva el estar instanciando, ya te comentaron uno, inyección de dependencias, o algo un poco peor, un registro, o algo muy malo, singleton.
  #16 (permalink)  
Antiguo 11/12/2012, 09:57
 
Fecha de Ingreso: octubre-2003
Mensajes: 364
Antigüedad: 20 años, 6 meses
Puntos: 1
Respuesta: Mi primer código POO - Dudas

Hola Genetix!
Me he leido antes el post que me habias puesto y la verdad es que han sido palabras muy duras... no he entendido mucho. Deberé investigar más ese tema que totalmente nuevo para mi.

Sobre mi ejemplo alguna ayuda?
Graciasssss
  #17 (permalink)  
Antiguo 11/12/2012, 10:38
Avatar de cluster28  
Fecha de Ingreso: enero-2008
Ubicación: Donostia - San Sebastián
Mensajes: 756
Antigüedad: 16 años, 4 meses
Puntos: 32
Respuesta: Mi primer código POO - Dudas

Cita:
Iniciado por GatorV Ver Mensaje
o algo muy malo, singleton.
Tan malo es? Yo pensaba que era una buena solución... Yo uso Singleton para gestionar la instancia de Bd y a su vez esa instancia la paso al los objetos que van usarla.
  #18 (permalink)  
Antiguo 11/12/2012, 10: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: Mi primer código POO - Dudas

Singleton es considerado un Anti-Pattern, ya que es casi lo mismo a una variable global, lo mismo es el registro, por eso lo mejor es usar DI, que aunque es un contenedor, al menos es un contenedor donde solo hay un punto de entrada y es fácilmente configurable.

Etiquetas: dudas, mysql, poo, primer, resultados, sql, tabla, usuarios
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

SíEste tema le ha gustado a 1 personas




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