martes, 29 de agosto de 2023

PHP: Una arquitectura de aplicación personalizada

Intentando resolver el problema planteado en esta entrada, me había puesto a crear (con mucha ayuda) un sistema MVC personalizado para aplicaciones PHP tal como se muestra en esta otra entrada. Tambien consideré aprender a fondo Codeigniter e incluso Laravel. Después de darle vueltas al asunto me he propuesto crear una arquitectura parecida a la MVC pero un poco más sencilla, que permita implementar buenas practicas de programación. Las principales características de esta opción son las siguientes:

  • No usa POO. Me parece que con la programación estructurada se mantiene más sencillo el código y a efectos prácticos, para los proyectos que pienso manejar, funciona bien.
  • Se divide el proyecto en dos bloques: Del lado dl cliente y del lado del servidor.
  • Se elimina el controlador principal que se usa en la arquitectura MVC.
  • Básicamente solo quedan las vistas y los modelos, las cuales se encuentran en carpetas distintas pero tienen los mismos nombres. Los controladores individuales se ha fusionado con el modelo pero su presencia es casi inperceptible.
  • Siempre se invoca primero el modelo y luego la vista: siempre en ese orden.
Estructura de la carpeta

El siguiente código es mi versión personalizada de una aplicación hecha con la arquitectura personalizada que he planteado.

index.php

<a href="mo/estudiante_listar.php"> Listar </a>

mo/a_conectar.php

<?php 

if (!($link=mysqli_connect("localhost","root","9810402254"))) 
   
	{ 
      
	echo "Error conectando a la base de datos.";
  
      exit(); 
   
	} 

if (!mysqli_select_db($link,"colegio")) 
   
	{ 
      
	echo "Error seleccionando la base de datos.";
  
      exit(); 
  
	}
  
?>

mo/estudiante_listar.php

<?php 
$dato = array();

require("a_conectar.php");
$rs = mysqli_query($link," select * from estudiantes ");

while($f = mysqli_fetch_array($rs))
        {  
	$dato[] = $f;
	}

mysqli_free_result($rs);
mysqli_close($link); 

require("../vi/estudiante_listar.php");
?>

vi/estudiante_listar.php

<table>
<tr>
<td>ID</td>
<td>NOMBRES</td>
<td>APELLIDOS</td>
</tr>
 
<?php foreach ($dato as $d): ?>
   <tr>
   <td><?php echo $d['id'] ?></td>
   <td><?php echo $d['nombres'] ?></td>
   <td><?php echo $d['apellidos'] ?></td>
   </tr>
<?php endforeach; ?>

</table>

sábado, 26 de agosto de 2023

PHP: Creando una aplicación MVC personalizada con POO

El siguiente código es una versión personalizada de una aplicación hecha en PHP que permite realizar la misma acción que la de esta entrada. Precisamente la única diferencia es que se implementa en una arquitectura MVC y la mayoría ha sido adaptado de otros códigos encontrados en Internet.

Estructura de carpetas

index.php

<?php 

require_once 'conf/config.php';

if(!isset($_GET["c"])) $_GET["c"] = constant("DEFAULT_CONTROLLER");
if(!isset($_GET["a"])) $_GET["a"] = constant("DEFAULT_ACTION");

// Establece la ruta donde se encuentra el controlador
$controller_path = 'controladores/'.$_GET["c"].'.php';

// Pregunta si el archivo con el controlador existe.
if(!file_exists($controller_path)) $controller_path = 'controladores/'.constant("DEFAULT_CONTROLLER").'.php';

/* Load controller */
require_once $controller_path;
$controllerName = $_GET["c"].'Controlador';
$controller = new $controllerName();

// crea $dato como un arreglo vacío
$dato = array();
// Si el método existe lo ejecuta y recibe el resultado en el arreglo $dato
if(method_exists($controller,$_GET["a"])) $dato = $controller->{$_GET["a"]}(); 


// Carga las vistas
require_once 'vistas/plantillas/cabeza.php';
require_once 'vistas/'.$controller->vista.'.php';
require_once 'vistas/plantillas/pie.php';

?>

conf/config.php

<?php

/* Valores de conexión a la base de datos*/
define("DB_HOST", "localhost");
define("DB", "colegio");
define("DB_USER", "root");
define("DB_PASS", "9810402254");

/* Controlador y acción (método) por defecto. */
define("DEFAULT_CONTROLLER", "estudiante");
define("DEFAULT_ACTION", "listar");

?>

controladores/estudiante.php

<?php 

// Este controlador usa un modelo 
require_once 'modelos/estudianteModelo.php';


class estudianteControlador 
	{
	//la variable vista contiene el archivo que mostrará la vista al usuario 
	public $vista ;

	public function __construct() 
		{
		
		}

		public function listar()
		{
		// Se asigna el nombre de la vista que se mostrará al usuario como resultado de esta acción 
		$this->vista = "estudianteListar";
		//Creación del modelo que accederá a la base de datos. 
		$m = new estudianteModelo();
		// Se ejecuta el método para listar y se obtiene el resultado en la variable rs
		$rs = $m->obtenerEstudiantes();
		// Se devuelve el arreglo obtenido. 
		return $rs;
		}

	}


?>

modelos/bd.php

<?php 

// Establece una conexión con la base de datos usando PDO y de acuerdo a los valores que se encuentran en el archivo de configuración.

require_once 'conf/config.php';

class bd {

	private $host;
	private $db;
	private $user;
	private $pass;
	public $conection;

	public function __construct() {		

		$this->host = constant('DB_HOST');
		$this->db = constant('DB');
		$this->user = constant('DB_USER');
		$this->pass = constant('DB_PASS');

		try {
           $this->conection = new PDO('mysql:host='.$this->host.'; dbname='.$this->db, $this->user, $this->pass);
        } catch (PDOException $e) {
            echo $e->getMessage();
            exit();
        }

	}

}

?>

modelos/estudianteModelo.php

<?php 

require_once 'modelos/bd.php';

class estudianteModelo {

	// la variable con guardará la conexión.
	private $con;

	public function __construct() 
			{

			}

	// Establece y guarda el valor de la conexión.
	public function establecerConeccion(){
		$dbObj = new bd();
		$this->con = $dbObj->conection;
	}


	public function obtenerEstudiantes(){
		
		// Establece la conexión.
		$this->establecerConeccion();
		// Realiza la consulta y guarda el resultado.
		$sql = "SELECT * FROM ESTUDIANTES";
		$s = $this->con->prepare($sql);
		$s->execute();
		// fetchAll — Devuelve un array que contiene todas las filas del conjunto de resultados.
		$rs = $s->fetchAll();
		// Retorna el valor del resutado.
		return $rs;
	}

// Considerar establecer un destructor para cerrar la conexión a la base de datos. Aunque el recolector de basura de PHP también se encargrá de esta operación.
	
}

?>

vistas/estudianteListar.php

<table>
    <tr>
        <th>Id</th>
        <th>Nombres</th>
        <th>Apellidos</th>

    </tr>
    <?php foreach ($dato as $r): ?>

        <tr>
            <td><?php echo $r["id"] ?></td>
            <td><?php echo $r["nombres"] ?></td>
            <td><?php echo $r["apellidos"] ?></td>

        </tr>

     <?php endforeach; ?>
</table>

vistas/plantillas/cabeza.php

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
</head>
<body>

vistas/plantillas/pie.php

</div>
</body>
</html>