Aplicando POO en PHP para organizar el codigo

Aplicando POO en PHP para organizar el código

Destinado:
Si sos de los que recién esta empezando en PHP o has leído sobre metodología orientada a objetos, o ya llevas tiempo viendo tutoriales pero todos tus practicas son un solo archivo donde mezclas PHP, HTML, CSS y Javascript... este post puede serte útil.

Objetivo
Emular un modelo de 3 capas con el cual lograremos organizar mejor nuestros proyectos, un código mas reutilizable, aplicar POO, aprender sobre extensiones para conectarse a base de datos mysql en PHP, principalmente guiar a los programadores recién iniciados.

No se pretende
Reemplazar ni crear un framework, que este aporte sea considerado la solución ideal, existe distintas formas de hacerlo y el punto de este articulo no es debatir que es mejor.




Es probable que mucho de los que empecemos no encontremos con código como el que ilustro en la imagen de abajo, un solo archivo que contiene todo. Esto es porque los tutoriales básicos no pretenden enseñar como organizar el código, salvo que lo hagan explicito. Quizá me equivoque y la mayoría ya sabe como organizar su código, pero si todavía tienes un código parecido al de abajo este articulo te sera útil.



Ok no hay mucho que explicar en el código de arriba. Primero conectamos a una base de datos, hacemos una consulta solicitando todos los usuarios de una tabla, y luego mostramos esos datos en una tabla porque son datos tabulados. 

¿Que pasaría si tuviese que hacer este tipo de cosas en un unos 50 archivos .php? Copiar y pegar la conexión a la base de datos  y demás partes que necesito ¿Que pasa si un día decido modificar algo que deberá actualizarse también en los 50 archivos?  ¿ y si tuviese mas de 1000 lineas de código?

Cuando hacemos una practica sencilla esto no esta mal pero cuando vamos a encarar un proyecto chico, mediano, o grande esto no es para nada bueno.

Arquitectura de 3 capas
Lo que se propone es separar las cosas.



Por un lado tendremos el contenido que se muestra en pantalla (HTML, CSS ,JS, algo de PHP), la llamamos capa de presentación
La siguiente capa, capa de negocio, se comunica con la capa de presentación, para recibir las solicitudes y devolver los resultados, y la capa de datos para interactuar con el gestor de base de datos. Podemos agregar que aquí se realizan las tareas relacionadas con las reglas del negocio por ejemplo: aplicar un descuento a los productos, que las fechas se traduzcan al español, validar los datos de un formulario antes de enviarlos a la base de datos, etc. No debe haber codigo sql.
Y por ultimo la capa de datos es la que se encarga de hacer consultas a la base de datos. Es decir, aquí encontraremos código SQL para insertar, devolver, modificar, etc.

APIs de PHP para acceder a las bases de datos de MySQL

¿Qué es una API?

Una Interfaz de Programación de Aplicaciones (o API de sus siglas en inglés), define las clases, métodos, funciones y variables que la aplicación necisita llamar para realizar una tarea. En el caso de aplicaciones de PHP que necesiten comunicarse con bases de datos, las APIs necesarias normalmente son expuestas mediante extensiones de PHP.

Las APIs pueden ser procedimentales y orientadas a objetos. Con una API procedimental se llaman a funciones para realizar tareas, con una API orientada a objetos se instancian clases y luego se llamana métodos sobre los objetos resultantes. De las dos, la última normalmente es la interfaz preferida, ya que es más moderna y conduce a un código mejor organizado.

Al escribir aplicaciones de PHP que necesitan conectarse a un servidor de MySQL, existen varias opciones de APIs disponibles.

¿Que API elegir?

PHP ofrece 3 APIs diferentes ellas son mysql, mysqli, y PDO, este ultimo es una capa de abstraccion. Esta es la recomendacion de PHP:

Se recomienda usar las extensiones mysqli o PDO_MySQL. No se recomienda usar la extensión mysql antigua para nuevos desarrollos, ya que ha sido declarada obsoleta a partir de PHP 5.5.0 y será eliminada en el futuro. El rendimiento global de las tres extensiones se considera aproximadamente el mismo. Aunque el rendimiento de la extensión aporta solamente una fracción del total del tiempo de ejecución de una consulta web de PHP. A menudo el impacto es tan bajo como 0.1%.


Aquellos que aun trabajan con mysql_connect() estan desactualizados. Yo usare para este post mysqli, la "i" al final significa improvement es decir es el mysql mejorado. Entre las ventajas de mysqli es que podemos trabajar de formar orientada a objetos dejando de lado el estilo procedimental que teníamos con mysql, aunque mysqli también es compatible con el estilo procedimental. Otra ventaja es el poder crear sentencias preparadas, preparadas para evitar inyecciones sql. Para mas información miren la documentación: http://www.php.net/manual/es/book.mysqli.php

Implementación



Partiendo del código anterior para evitarnos el trabajo de tener que copiar y pegar la conexión en cada archivo, crearemos un unico archivo .php. Este archivo contendrá una clase con un atributo que ser una instancia de la clase MySQLi. Creamos un archivo Modelo.php y escribimos el siguiente codigo:

<?php 
require_once "config.php";

class 
Modelo
{
protected $_db;

public function __construct()
{
$this->_db = new mysqli(DB_HOSTDB_USERDB_PASSDB_NAME);

if ( $this->_db->connect_errno )
{
echo "Fallo al conectar a MySQL"
return;
}

$this->_db->set_charset(DB_CHARSET);
}
}
?>


Esta clase nos servirá de plantilla para otras, todas las clases que accedan a base de datos deberan heredar de esta, de esta manera todas tendran acceso al atributo _db que es la instancia de mysqli que contiene todos los metodos y atributos para manejar la base de datos. config.php es un archivo que contiene constantes, deben modificarse en cada proyecto nuevo. Este es el archivo config.php

<?php 
define('DB_HOST','localhost');
define('DB_USER','root');
define('DB_PASS','112254');
define('DB_NAME','nombre de tabla');
define('DB_CHARSET','utf-8');
?>

Lo anterior es la base, lo queremos es que cada archivo que maneje datos herede Modelo. En nuestro ejemplo manejamos usuarios que están en una base de datos. Entonces crearemos una clase usuariosModelo, que lo único que hará es eliminar, buscar, modificar, agregar datos y no mas que eso, es decir nuestra capa de datos. Archivo usuariosModelo.php

<?php 
require_once "Modelo.php";

class 
usuariosModelo extends Modelo
{
public function __construct()
{
parent::__construct();
}

public function get_users()
{
$result $this->_db->query('SELECT * FROM usuarios');

$users $result->fetch_all(MYSQLI_ASSOC);

return $users;
}
}
 
 ?>

Si tuvieramos un e-commerce y necesitaramos datos de productos hariamos otra clase productoModelo. Gracias a la herencia cuando yo haga new usuariosModelo() este llamara al constructor de su padre, o sea, el constructor de Modelo, el cual iniciara mi atributo $_db. Gracias a $_db, que es una instancia de mysqli, podemos hacer ->query. 

->query() es un método que recibe la consulta y la ejecuta, devuelve true si la consulta tuvo exito, false si hubo error, si la consulta debe devolver resultados retorna un objeto mysqli_result. O sea result es una instancia de mysqli_result y tiene metodos, uno de ellos es ->fetch_all() que devuelve un array, la contante MYSQLI_ASSOC le indica que debe devolverme un array asociativo, veremos en el siguiente codigo que significa array asociativo.

El punto aquí es notar que el get_users() retorna un array de usuarios y nada mas, si tenemos que hacer algo con esos datos (adornarlos, mostrarlos en pantalla, ordenarlos, etc) lo hacemos en la capa de negocio. Podríamos agregar otros métodos como get_correo( $id ) de un usuario particular.

Bien ahora el siguiente paso es emular la capa de negocio(controlador), que dado a que no es muy complejo quedara reducido a un código sencillo. Archivo verUsuariosControlador.php

<?php  
  require_once 
"usuariosModelo.php";

$usuarioModel = new usuariosModelo();
$a_users $usuarioModel->get_users();
?>

Es importante que quede claro que cada vista tendrá su propio controlador, el controlador puede usar varios modelos (vuelvan a ver la imagen de arquitectura de 3 capas). El codigo es super sencillo ahora, solo instanciamos un usuarioModelo y llamamos su metodo get_users() que nos devuelve un array. Ya no copiaremos el mismo codigo una y otra ves, solo usaremos este método que se encuentra en un solo lugar. Podríamos hacer mas cosas aquí con este array dependiendo de las reglas del negocio pero para mantenerlo simple supondremos que el usuario pidió ver todos los usuarios y punto.

Y por ultimo nuestra capa de presentación (vista). archivo verUsuarios.php

<?php  
  require_once 
"verUsuariosControlador.php";
?>

<!DOCTYPE html>
 <html>
 <head>
  <title>Usuarios registrados</title>
  <link rel="stylesheet" type="text/css" href="css/table.css">
 </head>
 <body>
  <div class="CSSTableGenerator">
        <table>
            <tr>
                <td>
                    Id
                </td>
                <td>
                    Nombre
                </td>
                <td>
                    Correo
                </td>
            </tr>
            <?php foreach ($a_users as $row): ?>
            <tr>
                <td><?php echo $row['id']; ?></td>
                <td><?php echo $row['nombre']; ?></td>
                <td><?php echo $row['correo']; ?></td>
            </tr>
            <?php endforeach ?>                    
        </table>
    </div>      
 </body>
 </html>

Como ven requerimos un mínimo de php para mostrar datos lo demás es puro HTML y un archivo css.

Esto es lo que obtuvimos:




Modelo y config son dos archivos necesarios para poder crear un código reutilizable, los agregue en el gráfico para que quede claro lo que hicimos pero los podemos omitir(del gráfico). Todos los modelos deben heredar de modelo para quitarnos la tarea de andar creando la conexión.

Asi seria el gráfico si tuviésemos una vista verCarrito.php, omitiendo nuestra clase Modelo:






Como ven cada vista tiene su controlador que lo controla. Los controladores pueden llamar a varios modelos.


Como verán hable de arquitectura de 3 capas y parece que hablo del modelo MVC. Y esto es porque el modelo MVC es una forma de encarar el modelo de 3 capas, pero el MVC no es lineal porque el modelo puede comunicarse con la vista. Mientras que el concepto de arquitectura de 3 capas nos dice la vista no se comunica con el modelo directamente.


Por podríamos estructurar nuestras carpetas, de la siguiente forma:


-aplicacion

    -config.php

    -Modelo.php

-modelos

    -usuariosModelo.php

-controladores

    -verUsuariosControlador.php

-public

    -css

       -table.css

    -js

    -img

-verUsuarios.php


Obviamente tendríamos que cambiar las rutas de nuestro include_once.



Nota: Tienen que configurar el archivo config.php y tener una tabla usuarios con atributos id,nombre, correo.


Bueno se me ha quedado largo el post, espero les sea útil. Saludos
Aplicando POO en PHP para organizar el codigo
20 Puntos Score: 5/10
Visitas: 8710 Favoritos: 14
Ver los usuarios que votaron...
7 Comentarios Aplicando POO en PHP para organizar el codigo
que bien se mira este aporte gracias!
muy bueno... justo necesito aprender php... que IDE me recomiendas para la programacion en php???
@fagu_619 netbeans o sublime text 2
Exelente post muy buenos conceptos en especial para los que recien empiezan a programar que desdes sus origenes usen patrones como el MVC ayuda mucho a tener un codigo limpio y legible para los demas programadores  
Excelente aporte.
Gracias
pablo1416, estas equivocado por $users = $result->fetch_all(MYSQLI_ASSOC); porque no funciona y pero estos si sirve $users = mysqli_fetch_array($result);

Saludos
Para dejar un comentario Registrate! o.. eres ya usuario? Accede!