Organización de clases PHP para código limpio y seguro
Resumen
Un código organizado, limpio y seguro es esencial para ambientes profesionales en programación PHP. Una estructura adecuada no solo facilita la lectura del código, sino que también protege nuestros datos contra modificaciones indeseadas.
¿Por qué es importante separar las clases en archivos independientes?
Separar clases en archivos independientes contribuye a un diseño ordenado y lógico del código PHP. Cada clase debe residir en su propio archivo, facilitando su mantenimiento.
Nombramos el archivo con la primera letra en mayúscula, por ejemplo, OrdenBasicoClases.php.
Invocamos el archivo hermano mencionando únicamente su nombre.
Así facilitamos la detección de errores y realizamos actualizaciones rápidas.
¿Qué ventajas tiene trabajar de esta manera?
Separamos claramente la lógica (clases) de la ejecución y presentación.
Mejora la legibilidad y organización del proyecto.
Permite actualizaciones y mantenimiento eficiente.
¿Cómo asegurar que las propiedades de clases sean seguras?
Cuando se definen propiedades como públicas, cualquier parte del código podría modificarlas indebidamente. Para garantizar la seguridad de nuestra información:
Definimos propiedades como privadas para evitar manipulaciones externas.
Creamos métodos públicos específicos para obtener esta información (getters).
¿Cómo implementar métodos seguros para acceder a propiedades?
Creamos métodos que solo sirven para obtener datos, no para alterarlos. Ejemplo para obtener el título:
🧱 Separar la definición de clases: orden, reutilización y profesionalismo
Modularidad: Cada clase representa una entidad o comportamiento específico. Tenerla en su propio archivo refuerza su independencia conceptual.
Reutilización: Facilita la importación (require_once) desde múltiples scripts sin repetir código.
Mantenibilidad: Cambios a la clase no requieren editar múltiples archivos.
Escalabilidad: En proyectos con muchas clases y colaboradores, esta práctica mejora el flujo de trabajo y la comprensión general.
Depuración simplificada: Si hay errores, identificar la fuente se vuelve más ágil.
📁 Convención recomendada: nombra el archivo como la clase, con mayúscula inicial: Usuario.php, Producto.php, etc.
🧰 ¿Qué son los getters y setters?
Los getters y setters son métodos públicos que permiten acceder o modificar los atributos privados de una clase de manera segura y controlada.
🔸 Getters (obtener un valor)
Un getter devuelve el valor actual de un atributo. Suelen nombrarse con el prefijo get:
public function getNombre(): string {
return $this->nombre;
}
🔹 Setters (modificar un valor)
Un setter permite establecer o actualizar el valor de un atributo. Suelen nombrarse con el prefijo set:
public function setNombre(string $nuevoNombre): void {
$this->nombre = $nuevoNombre;
}
📌 Convención de nombres: getNombre(), setNombre(), getPrecio(), etc., para mantener claridad y consistencia.
✅ ¿Por qué usarlos?
Aplicás validaciones antes de modificar atributos.
Garantizás que los datos internos permanezcan en un estado válido.
Te preparás para que futuras modificaciones no afecten al código externo que ya usa tu clase.
🔒 Encapsulamiento: proteger atributos y controlar el acceso
Encapsular = blindar el interior de la clase. Solo se exponen métodos públicos que permiten interacción segura con sus propiedades internas.
🔑 Ventajas:
Impide accesos directos desde fuera.
Se pueden aplicar validaciones antes de modificar el estado interno.
Permite futuras mejoras sin romper el código existente: por ejemplo, transformar el getter en uno que formatee precios.
🎯 Comportamientos consistentes con atributos actualizados
Los métodos internos acceden a propiedades privadas mediante $this->atributo.
Esto permite mantener la coherencia del objeto, incluso cuando un valor cambia a través de un setter.
🧪 Validaciones y robustez profesional
Un paso más allá: no solo encapsular, sino proteger la integridad de los datos. Esto se logra validando entrada y, opcionalmente, lanzando excepciones:
publicfunctionsetStock(int$nuevoStock):void{if($nuevoStock<0){thrownewInvalidArgumentException("El stock no puede ser negativo.");}$this->stock=$nuevoStock;}
Siempre me había dado pereza aprender a usar/implementar clases en cualquier tipo de lenguaje...
Tuve que venir a un curso de PHP a ver lo maravilloso que es el lenguaje y lo importante que son las clases para mantener buenas prácticas, código mantenible fácilmente, y ver que no era para tanto!
public function UpdatePrice(float $new_price): void
{
// rules:
// If the new price is valid.
if (!is_numeric($new_price)) {
return; // or throw an exception
}
//The new price not negative.
if ($new_price < 0) {
return; // or throw an exception
}
// If the new price is the same as the current price, do nothing.
if ($new_price === $this->price) {
return; // No change needed
}
$this->price = $new_price;
}
$course->UpdatePrice(9.99); // Update the price to $9.99
<?php
require "title.php";require "newlevel.php";$title =newtitle("Curso profesional de PHP y Laravel","Aprende PHP y Laravel desde 0",["PHP","Laravel","HTML","CSS","JavaScript"]);$title->addTag("Backend");$title->addTag("Frameworks");$title->addTag("PHP");$title->addTag("");$title->addTag("HTML");$newlevel =newnewlevel();$newlevel->setLevel("PROFESIONAL",4000,"Este curso está dirigido a personas que quieren superar sus límites con PHP.");$newlevel->getPrice();$newlevel->getDescription();$course =["info"=>["PHP para cualquier nivel","PHP para novatos","PHP para medios","PHP para avanzados"]];$level =["BASICO"=>["precio"=>1000,"descripcion"=>"Curso para quienes no cuenten con conocimientos previos."],"MEDIO"=>["precio"=>2000,"descripcion"=>"Este curso está dirigido a estudiantes con conocimientos básicos de Php."],"AVANZADO"=>["precio"=>3000,"descripcion"=>"Este curso está dirigido a personas que ya tienen experiencia programando con Php."],"PROFESIONAL"=>["precio"=> $newlevel->getPrice(),"descripcion"=> $newlevel->getDescription()]];$actuallevel = $_GET['level']??"BASICO";$actualprice = $level[$actuallevel]["precio"];$description = $level[$actuallevel]["descripcion"];$date =date("F j, Y, g:i a");$archived =false;$status = $archived ?"Archivado":"Activo";?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title><?= $title->getTitle()?></title></head><body><h1>Bienvenido|<?= $title->getTitle()?></h1><h2><?= $title->getSubtitle()?></h2><p>Fecha de publicación:<?= $date?></p><!--MANERASDEESCRIBIRCONDICIONALESENPHP<?php
// Condicionalesif($archived){ echo '<p style="color: red;" >Este curso esta archivado</p>';}else{ echo '<p style="color: green;">Este curso esta activo</p>';}?><?php if($archived):?><p style="color: red;">Este curso está archivado</p><?php else:?><p style="color: green;">Este curso está activo</p><?php endif;?>--><p>El curso está <span
style="<?= $archived ? 'color: red;' : 'color: green;' ?>"><?= $status ?></span></p><form action="" method="GET"><p>Este curso es de nivel:<select name="level" onchange="this.form.submit()"><option value="BASICO"<?= $actuallevel =='BASICO'?'selected':''?>>BASICO</option><option value="MEDIO"<?= $actuallevel =='MEDIO'?'selected':''?>>MEDIO</option><option value="AVANZADO"<?= $actuallevel =='AVANZADO'?'selected':''?>>AVANZADO</option><option value="PROFESIONAL"<?=$actuallevel =="PROFESIONAL"?"selected":""?>>PROFESIONAL</option></select></p></form><p><?= $description ?></p><p>El curso <strong><?= $course["info"][0]?? $course["info"]?></strong> cuesta: $<?= $actualprice ?></p><p><p><strong>Etiquetas</strong></p><ul><?php foreach($title->getTags()as $tag):?><li><?= $tag ?></li><?php endforeach;?></ul></body></html>
<?php
require 'Course.php';$course =newCourse(title:"Curso profesional de PHP y Laravel",subtitle:"Aprende desde cero y crea aplicaciones completas con PHP y Laravel",description:"En este curso aprenderas a desarrollar aplicaciones web completas utilizando PHP y Laravel",tags:["PHP","Laravel","Desarrollo Web"]);$course->addTag("Frameworks");$course->addTag("Desarrollo de Software");$course->addTag("HTML5");$course->addTag("");$course->changeTitle("Curso de PHP y Laravel");?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title><?= $course->getTitle()?></title></head><body><h1>Bienvenido al <?= $course->getTitle()?></h1><h2><?= $course->getSubtitle()?></h2><p><?= $course->getDescription()?></p><p><strong>Etiquetas:</strong><ul><?php foreach($course->getTags()as $tag):?><li><?= $tag ?></li><?php endforeach;?></ul></p></body></html>
//Cambiar atributo nombre de Author.php// Setter para el nombrepublicfunctionsetNombre(string $nuevoNombre):void{ $this->nombre = $nuevoNombre;}//Uso del setter en el archivo principal<?php
require_once 'Author.php';// Crear autores del género horror$king =newAuthor(genero:"Horror",nombre:"Stephen King",fechaNacimiento:"1947-09-21",peliculas:["Carrie","El resplandor","Misery","It"]);// Cambiar el nombre usando el setter$king->setNombre("Esteban Rey");$carpenter =newAuthor(genero:"Horror",nombre:"John Carpenter",fechaNacimiento:"1945-01-16",peliculas:["Halloween","The Fog","Escape from New York","Big Trouble in Little China"]);$carpenter->setNombre("Juan Carpintero");?>
Para proteger tus datos públicos, es esencial seguir buenas prácticas de programación y seguridad. En el contexto de PHP, asegúrate de que las propiedades de tus clases sean privadas, lo que evita modificaciones no deseadas desde el exterior. Implementa métodos que controlen el acceso a estos datos, como getters y setters, garantizando que la información sensible no sea expuesta. Además, verifica siempre la validación de datos ingresados por los usuarios para prevenir inyecciones de código y otras vulnerabilidades. Mantener tu código limpio y organizado también contribuye a la seguridad general de tus aplicaciones.