Lo que hago yo es tratar de emular a un ORM en cosas básicas. Por ejemplo, una persona es una entidad, pero esa persona puede tener varios números telefónicos a los que puede ser contactado, en un esquema de base de datos SQL, necesitaríamos 2 tablas para poder encapsulara a 1 entidad que es "persona".
Este es el esquema de base de datos:
tabla persona, atributos: id, nombre, direccion.
tabla agenda, atributos: id, id_persona, telefono.
Están relacionadas por la llave local agenda.id_persona, y la llave foránea persona.id.
De tal forma que mediante POO accederé a la entidad "persona" mediante una única instancia, la cual tendrá métodos como getNombre, getDireccion, getTelefonos.
//archivo persona.php
Código PHP:
Ver original<?php
class persona {
private $nombre;
private $direccion;
private $telefonos=array();
public function setNombre($nombre){
$this->nombre=$nombre;
}
public function setDireccion($direccion){
$this->direccion=$direccion;
}
public function setTelefonos($telefonos){
$this->telefonos=$telefonos;
}
}
?>
Ahora utilizamos una clase llamada dbPersona que es la encargada de acceder a la base de datos, y llenar instancias de la clase persona con los registros tomados de la base de datos.
Archivo dbPersona.php
Código PHP:
Ver original<?php
require_once 'persona.php';
class dbPersona {
private $host = "localhost";
private $db = "persona";
private $user = "root";
private $pass = "nose";
private $link;
public function __construct(){
$this->conectar();
}
private function conectar(){
}
public function getAll(){ //DEVUELVE UNA COLECCION DE CLASES, NO UNA COLECCION DE ARRAYS
$personas[]=$this->fetch($row);
}
return $personas;
}
public function getById($id){ //DEVUELVE UNA INSTANCIA DE LA CLASE PERSONA SEGUN EL ID.
$persona=$this->fetch($row);
return $persona;
}
private function getTelefonos($id_persona){
$result=mysql_query("SELECT telefono FROM agenda WHERE id_persona='$id_persona'",$this->link);
return $telefonos;
}
private function fetch($row){
$persona=new persona();
$persona->setId($row['id']);
$persona->setNombre($row['nombre']);
$persona->setDireccion($row['direccion'];
$telefonos=$this->getTelefonos($row['id']);
$persona->setTelefonos($telefonos);
return $persona;
}
}
?>
Los archivos anteriores corresponden a la capa Modelo ( según el modelo MVC).
Para acceder a los datos de una persona:
Archivo index.php
Código PHP:
Ver original<?php
require_once 'dbPersona.php';
$db= new dbPersona();
$personas= $db->getAll();
foreach($personas as $persona){
echo $persona->getNombre();
foreach($persona->getTelefonos() as $telefono){
echo $telefono;
}
}
?>
De esta manera logramos encapsular los registros de una tabla relacional en entidades manejables desde una única instancia. A esto se le llama persistencia.
Debo aclarar que no utilizo la interfaz mysql de PHP sino la interfaz mysqli, así que no certifico la calidad del código jojojo ;)
También aclaro que la parte del modelo lo genero con un script que creé para facilitarme las cosas, pues escribir la parte del Modelo puede llegar a ser doloroso, pues consume tiempo, y es algo repetitivo, pero vale la pena el esfuerzo porque es mucho más fácil alimentar a los demás archivos de la capa Controlador y Vista con métodos intuitivos y objetos encapsulados (todo dentro de un mismo paquete, para una persona: su nombre, dirección, y lista de números telefónicos).
La conexión la hago en otro archivo "conectar.php" del cual heredo para todas la clases que accedan a la base de datos.
En resumen, en vez de acceder a los datos como simples arrays:
echo $persona['nombre'];
Lo hacemos mediante POO, donde $persona no es un array sino una clase:
echo $persona->getNombre();
Acceder a los atributos mediante métodos da mucha mayor flexibilidad.
A como puedes notar, el controlador "index.php" es bastante sencillo y extremadamente simple de comprender.
Recuerda que el código de la capa Modelo (en este ejemplo la clase persona y dbPersona) sólo se escribe una vez,
así que vale la pena el esfuerzo, porque así liberas de mucho peso y complejidad a la capa Controlador y Vista, que suele ser la parte dinámica
de una aplicación, y la parte que puede crecer y crecer, y es lo que cambia más durante el ciclo de vida de una aplicación.
Ahora, para el problema de "eficiencia" donde sólo quisieras mostrar el nombre de la persona, pero sin tener que cargar todos los datos de esa persona y
perder el tiempo cargando esos datos, podríamos hacer que al llamar al método getNombre, si el atributo nombre no ha sido establecido, haga una
consulta a la base de datos; así sólo se irán cargando dinámicamente los datos necesarios.
Código PHP:
Ver originalrequire_once 'dbPersona.php';
class persona {
private $id;
private $nombre;
public function setNombre($nombre){
$this->nombre=$nombre;
}
public funcion getNombre(){
if(!isset($this->nombre){ $db = new dbPersona();
$this->nombre=$db->getNombre($this->id);
}
return $this->nombre;
}
}
El método getAll de la clase dbPersona, de primas a primeras sólo se encargaría de devolver una colección de clases
semi vacías, donde sólo se inicialicen los id;
Código PHP:
Ver originalpublic function getAll(){
$result="SELECT id FROM persona";
$persona=new $persona();
$persona->setId($row['id']);
$personas[]=$persona;
}
return $personas;
}
public function getNombre($id){
"SELECT nombre FROM persona WHERE id='$id'";
return $nombre;
}
En nuestro controlador el flujo de datos se vería así
Código PHP:
Ver originalrequire_once 'dbPersona.php';
$db= new dbPersona();
$personas=$db->getAll(); //devuelve clases donde sólo los id han sido inicializados
foreach ($personas as $persona){
echo $persona->getNombre()// como el atributo nombre está vacío, hace la consulta a la DB.
//imprime el nombre;
echo $persona->getNombre()//el atributo nombre ya ha sido inicalizado, por ende no ejecuta la consulta,
// y devuelve el valor inmediatamente.
}
Aunque en realidad no sé qué tan eficiente - o no- puede ser eso jojo.
A modo de tip, en mi tiempo libre durante 2 días escribí un script para crear el 80% de la capa de Modelo (me falta pulir el script :P )
una vez terminado, sólo modifico un archivo YAMAL en el cual escribo lo siguiente:
Código XML:
Ver originalall:
database:
host: localhost
user: root
pass: nose
esquema: curso
modelo:
persona: id, nombre, apellido, direccion
agenda: id, id_persona, telefono
----
Eso es todo, luego ejecuto el script y casi casi se me genera todo el código necesario. jojojo.
Así que ánimo. Imagino que habrán mejores maneras de hacerlo, pero mientras continuo aprendiendo, seguiré trabajando así por el momento ;)