Curso de PHP Esencial: La Ruta Directa a Laravel y CodeIgniter

En este curso, vamos a ver las bases para poder entender PHP y seguir nuestro aprendizaje desde un framework como Laravel y CodeIgniter; esta fue la forma en la cual yo aprendí a programar en CodeIgniter y Laravel, conocí las bases de PHP y luego migré a CodeIgniter 2 y desde CodeIgniter 3 a Laravel.

PHP es otro lenguaje de programación para la web, de los muchos que existe, amado y odiado por igual pero, lo que si es seguro, es que, muy rápidamente podemos tener programación espaguetti en un proyecto, aunque sea pequeño en PHP y es por eso, que soy un fuerte defensor de que, desde bases tempranas (las dadas en este curso) saltar a un framework para poder enfocarse en lo importante, desarrollar la app y aprender y no perder tiempo reinventando la rueda creando esquemas ya bien planificados en los framewoks.

En este curso veremos:

  • PHP y su entorno
  • Variables y tipos de datos
  • Funciones
  • Clases y Herencia
  • Retos y ejercicios de programación

Por lo tanto, es un curso bastante conciso para que entres en este mundo y desarrolles tus primeras aplicaciones con PHP.

Herramientas necesarias para el mini-curso

En esta sección vamos a hablar sobre las herramientas que necesitaremos para llevar a cabo este minicurso.

Editor de código

Como siempre recomiendo, lo más práctico es usar un editor de código. Yo utilizo Visual Studio Code (VS Code), que luce de la siguiente forma. Aquí tengo abierto un proyecto en Python con Flash, pero esta interfaz es la misma para cualquier tipo de proyecto.

No es obligatorio usar VS Code; podrías programar incluso en Bloc de notas, aunque sería bastante masoquista de tu parte. Te recomiendo usar un editor de altura, como VS Code, por varias razones:

  1. Es multiplataforma.
  2. Soporta múltiples tecnologías.
  3. Es estable y funciona muy bien en proyectos grandes.

Si decides usar VS Code, la única extensión que necesitas instalar es la de PHP. Puedes buscarla en el apartado de extensiones; normalmente se llama “PHP” y no requiere configuraciones adicionales.

Navegador web

Puedes usar el navegador que prefieras. Yo utilizo Google Chrome, pero cualquier navegador moderno funcionará perfectamente para este curso.

PHP y entorno de desarrollo

PHP es esencial para este curso, y existen muchas formas de instalarlo, dependiendo del sistema operativo:

Windows o macOS: Recomiendo Laravel Herd, que es fácil de instalar y configurar. Aunque su nombre pueda parecer avanzado, es muy intuitivo y te permitirá tener todo listo para trabajar con proyectos PHP, Laravel o CodeIgniter.

Linux: Aquí la instalación depende de la distribución y requiere comandos específicos. Por ejemplo, podrías usar XAMPP, LAMP o consultar guías para tu sistema operativo.

 Laravel Herd y herramientas similares facilitan el desarrollo, ya que crean automáticamente URLs limpias para tus proyectos, a diferencia de otros entornos como XAMPP o WAMP, donde todo es manual.

Hola Mundo

Pasos previos:

  • Iniciar el servidor, Lo siguiente que tienes que hacer es iniciar tu servidor.
    Si usas Laravel Herd, al abrirlo se iniciarán automáticamente todos los servicios necesarios, en el resto, como XAMPP, usualmente hay un botón que dice iniciar, debes estar pendiente de si ocurre algún error como si ya hay un puerto iniciado, etc, recuerda que SOLO puedes tener un servicio tipo XAMPP como Laragon o Laravel Herd activo por vez.
    • Una vez iniciado, al abrir localhost en tu navegador, deberías ver una página de bienvenida de tu servidor (Apache, Nginx o el que uses).
  • Editor, seleccionas tu editor, tu VSC el recomendado y creas una carpeta en tu servidor:
    • Si estás usando Laragon o Herd, la ruta por defecto sería algo como:
      • C:\Users\TuUsuario\Laragon\www
      • C:\Users\TuUsuario\Herd
    • Creas una carpeta, sugerido llamado “pruebas” y la arrastras a tu VSC.

Escribir nuestro primer “Hola Mundo”

En PHP, todo el código va dentro de las etiquetas:

C:\Users\TuUsuario\Herd\test.php

<?php
// Aquí va tu código PHP

Para mostrar texto en pantalla, usamos la función echo.

Por ejemplo:

C:\Users\TuUsuario\Herd\test.php

<?php
echo "Hola Mundo";

Las comillas pueden ser simples 'Hola Mundo' o dobles "Hola Mundo".

Cada instrucción debe terminar con un punto y coma ;.

Guarda el archivo y recarga la página en tu navegador, en Laravel Herd o Laragon:

http://pruebas.test/test.php

Otros:

http://localhost/pruebas/test.php

¡Ahí tienes tu primer “Hola Mundo” en PHP! 🎉

Primeros pasos con PHP

Nos quedamos en el punto donde ya aprendimos a mostrar nuestro primer Hola Mundo en PHP sin complicaciones.

Recordemos que, para trabajar con PHP y colocar cualquier contenido dinámico, siempre debemos usar la etiqueta de apertura <?php ?>. A partir de aquí podemos aprovechar todo el potencial de PHP, que nos permite realizar operaciones dinámicas, trabajar con programación orientada a objetos, manejar fechas, variables, clases y mucho más. Todo esto lo iremos viendo poco a poco a lo largo del curso.

Mi objetivo no es enseñarte únicamente cómo crear variables o funciones, sino darte las bases para que comprendas el razonamiento lógico detrás de cada acción, y entiendas el “porqué” de lo que estamos haciendo.

RECOMENDACIÓN: Ver el Código Fuente en el navegador

Antes de avanzar, es recomendable que siempre revises el código fuente de la página:

En Windows o Linux: clic derecho → Ver código fuente

En Mac: Ctrl + U

El navegador solo entiende HTML, CSS y JavaScript, más archivos estáticos como PDFs, imágenes o videos. Todo lo que genera PHP se interpreta en el servidor y se envía como HTML al navegador. Por ejemplo, aunque tu archivo sea PHP, el navegador solo renderiza HTML.

Desde el apartado de código fuente, es una herramienta útil para que veas exactamente que es lo que se reenderiza.

HTML vs PHP

Para ilustrar esto, podemos crear un archivo test2.html con el mismo mensaje que pusimos en PHP. Al abrirlo, verás que la salida en el navegador es la misma, aunque la ruta cambie.

Esto demuestra un principio clave: el navegador solo entiende HTML, CSS y JavaScript. PHP sirve para agregar dinamismo a estas páginas, por ejemplo:

<?php
echo 5 + 5; // Esto mostrará 10
?>

Con PHP podemos:

  • Realizar operaciones dinámicas
  • Mostrar fechas
  • Conectar a bases de datos

Crear contenido dinámico que luego se sirve como HTML

En contraste, si intentamos colocar operaciones como 5 + 5 con PHP directamente en un archivo HTML, el navegador no sabrá qué hacer y simplemente lo mostrará como texto.

Buenas Prácticas con Etiquetas PHP

Cuando mezclamos PHP con HTML, es importante cerrar correctamente las etiquetas.

Ejemplo:

<?php
echo "Hola Mundo";
?>
<h1>Este es un título HTML</h1>

La apertura <?php indica el inicio del código PHP.

El cierre ?> es necesario si después seguimos con contenido HTML.

Si todo el archivo es PHP puro, no es obligatorio cerrar la etiqueta, y de hecho, muchas veces se recomienda no cerrarla para evitar espacios en blanco o inyecciones accidentales.

Código Espagueti en PHP

Cuando mezclamos lógica, HTML y operaciones en un solo archivo, obtenemos lo que se conoce como código espagueti:

  • Lógica de negocios
  • Conexiones a base de datos
  • Validaciones de usuarios
  • HTML estático

Esto funciona, pero es difícil de mantener y propenso a errores. Por eso, aunque debemos aprender PHP “puro” para entender las bases, lo ideal es usar un framework.

Frameworks para Evitar Código Espagueti

Un framework nos permite:

  • Seguir buenas prácticas automáticamente
  • Separar lógica de presentación
  • Evitar errores comunes en PHP puro

Ejemplos de frameworks livianos que podemos usar para aprender:

  • Laravel
  • CodeIgniter
  • Lumen

Estos frameworks nos ayudan a crear aplicaciones estructuradas y mantenibles, evitando que terminemos con un solo archivo lleno de PHP y HTML mezclados.

Resumen

  • PHP se interpreta en el servidor y entrega HTML al navegador.
  • Siempre usar <?php ?> para código PHP.
  • Revisar el código fuente del navegador para entender lo que realmente se envía.
  • Cerrar etiquetas PHP si combinamos con HTML.
  • Evitar código espagueti usando frameworks.

Con esto, tenemos la base sólida para empezar a trabajar con PHP de forma correcta, entendiendo la diferencia entre contenido estático y dinámico, y preparados para avanzar hacia operaciones más complejas y el uso de frameworks.

Variables en PHP

En esta sección hablaremos sobre variables en PHP. Realmente, lo de los tipos de datos no tiene mucho sentido en este contexto, ya que este es un artículo bastante antiguo que estoy actualizando. Pero volviendo al tema: doy por hecho que tú ya sabes programar y estás aquí para aprender PHP y dar el siguiente paso, que es luego saltar a los frameworks, que es uno de los objetivos de este curso.

Aun así, vamos a dar rápidamente una definición de variable:
Una variable es simplemente una forma de acceder a la memoria. Es decir, tenemos una información (un número entero, un string, un booleano, etc.) y queremos guardarla para poder usarla a lo largo de nuestra aplicación.

Por ejemplo, supongamos que estás creando un formulario para solicitar datos de una persona, como nombre, edad, etc. Cada uno de estos datos puede almacenarse en una variable, como:

  • Una variable para el nombre
  • Una variable para la edad

El uso que hagas de estas variables dependerá del propósito de tu aplicación, la lógica de negocio, y demás. En términos generales, esto es lo que es una variable.

Sintaxis de variables en PHP

En PHP, todas las variables comienzan con el símbolo $. Esto es una particularidad interesante de PHP, ya que la mayoría de los otros lenguajes como Java, JavaScript, C#, entre otros, no utilizan el $.

Algunas reglas importantes:

  • No pueden contener espacios. Por ejemplo, nombre persona no es válido.
  • No pueden comenzar con números ni caracteres especiales.

Puedes usar letras, guiones bajos _ o mayúsculas, siguiendo las convenciones de nombres:

  • Camel case: nombrePersona
  • Snake case: nombre_persona

Personalmente, prefiero camel case, pero es cuestión de gustos. Lo importante es mantener coherencia y legibilidad.

Tipos de datos y buenas prácticas

En PHP, el tipo de dato es opcional al declarar una variable, a diferencia de otros lenguajes como Java o C#. Sin embargo, siempre es recomendable especificarlo. Por ejemplo:

$name = "Andrés"; // string
$edad = 25;       // integer
$activo = true;   // boolean

Podemos verificar el tipo de dato usando la función gettype():

echo gettype($name); // string
echo gettype($edad); // integer

Es importante recordar:

  • No declares nombres locos o ilegales para las variables.
  • No uses espacios ni caracteres extraños.
  • Puedes incluir números después de la primera letra si es necesario.

Tipos de variables en PHP

Las variables son el mecanismo para acceder a la memoria que ponen a nuestra disposición los lenguajes de programación; en este artículo veremos como crear una variable en PHP, particularidades de las mismas y tipos de datos en PHP.

Los nombres de variables en PHP deben de comenzar con el signo '$' (sin comillas) seguido por el nombre de la misma el cual no puede ser nulo, ni comenzar por un número o por un carácter especial.

Ejemplo de variables inválidas en PHP

$1var;  // no puede comenzar por un numero
$ var;  // no puede comenzar con un espacio vacio
$v ar   // tampoco puede contener espacios vacios
var   // falto el $

Ejemplo de variables válidas en PHP

$var;
$var1;
$_var;

Son sensibles a mayúsculas y minúsculas.

Ejemplo de variables distintas en PHP

$Var;
$VAr;
$var;

En PHP no es necesario especificar el tipo de dato antes de utilizarlas, se declaran al momento de asignarle un valor.

PHP soporta ocho tipos primitivos

Cuatro tipos escalares:

Dos tipos compuestos:

  • object
  • array

Y dos tipos especiales:

  • resource
  • NULL

Para terminar presentamos un sencillo ejemplo de los datos de una persona utilizando varios de los tipos de variables que ya vimos.

<?php
$anos = 24; //variable de tipo integer.
$nombre = "pepe"; //variable de tipo string.
$casado = true; //variable de tipo  boolean.
$sueldo = 4025.43; //variable de tipo float
// arreglo de 4 tipos de datos
$persona_array = array('anos'=>$anos , 'nombre'=>$nombre , 'casado'=>$casado, 'sueldo'=>$sueldo);
// objeto de 4 tipos de datos
$persona_object = (object)$persona_array;
// mostramos los valores de las variables
echo "variable de tipo integer: ";
echo $anos;
echo "<br>";
echo "variable de tipo string: ";
echo $nombre;
echo "<br>";
echo "variable boolean: ";
echo $casado;
echo "<br>";
echo "variable de tipo double: ";
echo $sueldo;
echo "<br>";
echo "variable de tipo object: ";
echo $persona_object->anos;
echo "-";
echo $persona_object->nombre;
echo "-";
echo $persona_object->casado;
echo "-";
echo $persona_object->sueldo;
echo "<br>";
echo "variable de tipo array:";
echo "<br>";
var_dump($persona_array);
?>

Al interpretar el código anterior:

variable de tipo integer: 24
variable de tipo string: pepe
variable boolean: 1
variable de tipo double: 4025.43
variable de tipo object: 24-pepe-1-4025.43
variable de tipo array:
array(4) { ["anos"]=> int(24) ["nombre"]=> string(4) "pepe" ["casado"]=> bool(true) ["sueldo"]=> float(4025.43) }

Booleanos en PHP

Este es el tipo de dato más simple que existe en PHP; un boolean expresa un valor de verdad, el cual solo puede tener uno de dos estados; TRUE o FALSE; en ambos casos, son insensibles a mayúsculas y minúsculas.

<?php
$verdad = TRUE; // asigna el valor TRUE
$falso = FALSE; // asigna el valor FALSE
?>

TRUE equivale al valor 1 y FALSE equivale al valor 0; es decir puedes reemplazar el valor 1 y 0 por TRUE y FALSE respectivamente.

Integer en PHP

Un entero o integer por definición es un número con signo sin parte decimal; la misma regla se aplica en PHP.

Notaciones de los enteros en PHP

Los integer pueden ser especificados mediante notación decimal (base 10), hexadecimal (base 16), octal (base 8) o binaria (base 2), opcionalmente precedidos por un signo (- o +) según sea el caso:

  • Para usar la notación octal, se antepone al número un 0 (cero).
  • Para usar la notación hexadecimal, se antepone al número un 0x.
  • Para usar la notación binaria, se antepone al número un 0b.

Ejemplo: Enteros literales en php

<?php
$a = 1234; // número decimal
var_dump($a);
$a = -123; // un número negativo
var_dump($a);
$a = 0123; // número octal (equivalente a 83 decimal)
var_dump($a);
$a = 0x1A; // número hexadecimal (equivalente a 26 decimal)                    
var_dump($a);
$a = 0b11;
var_dump($a);// número binario (equivalente a 3 en decimal) 
?>

Al interpretar el código anterior:

int(1234) 
int(-123) 
int(83) 
int(26) 
int(3)

Rango de un integer en php (desbordamiento de enteros)

Si PHP encuentra un número fuera de los límites de un integer, se interpretará como un float en vez de un integer.

Ejemplo: Desbordamiento de enteros en sistemas 32-bits en php

<?php
$large_number = 2147483647;
var_dump($large_number);                      
$large_number = 2147483648;
var_dump($large_number);                      
?>

Al interpretar el código anterior:

int(2147483647)
float(2147483648)

Ejemplo: Desbordamiento de enteros en sistemas 64-bits en php

<?php
$large_number = 9223372036854775807;
var_dump($large_number);                      
$large_number = 9223372036854775808;
var_dump($large_number);                      
?>

Al interpretar el código anterior:

int(9223372036854775807)
float(9.2233720368548E+18)

¿Como utilizarlo en una estructura de control?

<?php
// no es necesario realizar la comparacion en un tipo boolean
if ($verdad == TRUE) {
    echo "esto es verdad\n";
}
// porque se puede escribir asi
if ($verdad) {
    echo "esto es verdad\n";
}
?>

Al interpretar el código anterior:

esto es verdad 
esto es verdad

Float en PHP

Un float o números de punto flotante es un número con signo con parte decimal; la misma regla se aplica para PHP.

Notaciones de números de punto flotante en PHP

Ejemplo de números punto flotante

<?php
  $a = 1.234;
  var_dump($a);
  $b = 1.2e3; 
  var_dump($b);
  $c = 7E-10;
  var_dump($c);
?>

Al interpretar el código anterior:

  float(1.234) 
  float(1200) 
  float(7.0E-10)

Rango de números punto flotante

El tamaño de un flotante depende de la plataforma, aunque un valor común consiste en un máximo de ~1.8e308 con una precisión de aproximadamente 14 dígitos decimales (lo que es un valor de 64 bits en formato IEEE).

NULL en PHP

El valor NULL indica que la variable que tiene asignado dicho valor, no tiene ningún valor asignado; es decir, indica que la variable no tiene valor alguno.

La variable se considera nula (NULL) cuando:

  • Se le ha asignado la constante NULL.
  • No se le a ha asignado ningún valor.
  • O simplemente se ha destruido con el método unset().

Conversión de tipos

En esta entrada hablaremos un poco sobre la conversión de tipos en PHP al momento de realizar distintas operaciones como matemáticas.

PHP no es un lenguaje fuertemente tipado lo que significa que no controla los tipos de datos de las variables y si se desea realizar operaciones, PHP realiza una conversión de tipos según la operación que se desee realizar; para el siguiente ejemplo:

$string1 = "8";
$string2 = "4cuatro";
$stringFinal = $string1 + $string2;
echo "Vamos a sumar $string1 + $string2 <br>";
echo "resultado $stringFinal";

Da la siguiente salida:

Vamos a sumar 8 + 4cuatro 
resultado 12

Al intentar realizar una operación de suma, el intérprete de PHP convierte automáticamente el texto contenido por la variable $string1 de "8" a 8, comportamiento similar sucede con la variable $string2, el intérprete convierte a valor numérico hasta que consigue el primer caracter "c" dando como conversión implícita para realizar la operación de suma el valor 4 y se suman ambos valores.

Si por el contrario, aplicamos el siguiente ejemplo:

$string1 = "8";
$string2 = "c4uatro";
$stringFinal = $string1 + $string2;
echo "Vamos a sumar $string1 + $string2 <br>";
echo "resultado $stringFinal";
Vamos a sumar 8 + c4uatro 
resultado 8

El intérprete nuevamente realiza $string1 de "8" a 8, pero para el valor almacenado en la variable $string2 el intérprete detecta que el primer carácter no es numérico al ser "c" y por lo tanto no hay nada que convertir y la variables es evaluada por defecto como cero.

Otros aspectos del tipo de dato NULL

La constante NULL es insensible a mayúsculas y minúsculas.

Concatenación en PHP

La concatenación en PHP se hace con el punto ., no con el + como en otros lenguajes:

echo "Hola " . $name;

Esto funciona para unir strings. Si quieres incluir variables directamente dentro de un string, puedes usar comillas dobles:

echo "Hola $name"; // imprime Hola Andrés

Con comillas simples, el contenido se toma como texto literal:

echo 'Hola $name'; // imprime Hola $name

Esto es útil cuando quieres imprimir algo sin que PHP lo interprete como variable.

Operaciones con variables

Puedes realizar operaciones aritméticas según el tipo de dato.

La concatenación solo funciona con strings; otros tipos pueden requerir conversión.

Los booleanos, enteros y flotantes se comportan según su tipo.

Ejemplos:

$numero = 10;
$decimal = 10.5;
$esValido = true;
echo $numero + 5;       // 15
echo $decimal + 4.5;    // 15
echo $esValido ? 'Sí' : 'No'; // Sí

Comillas simples para texto literal.

Esto sirve como base para entender cómo funcionan las variables en PHP y practicar su uso antes de avanzar a funciones, clases y otras estructuras más avanzadas.

echo  'Hola '. $name. ' Hola';
echo  "Hola $name Hola";

Resumen

Las variables comienzan con $.

  • No pueden contener espacios ni empezar con números.
  • Usa camel case o snake case para legibilidad.
  • Los tipos de datos son opcionales, pero recomendables.
  • Concatenación con . o interpolación con comillas dobles.

Funciones

Vamos ahora con las funciones en PHP. ¿Cómo demonios podemos implementar funciones en PHP?
Antes de eso, recordemos el concepto básico: las funciones existen para reutilizar código.
Por ejemplo, aunque no hemos visto prácticamente nada, supongamos que esto es crucial o muy importante para ti, y quieres imprimirlo en dos partes: una en el header y otra en un menú.

Entonces, ¿cómo harías tal cual hemos mostrado hasta este punto? Tendrías que duplicarlo en esas partes cruciales. Tal como te comentaba antes: abrir el bloque PHP aquí, imprimir el código, luego abrir otro bloque allá, volver a imprimirlo… lo cual obviamente es un problema.
Imagina que es más código, que incluye conexión a la base de datos, validaciones o que simplemente cambia en el futuro. Claramente esto es impráctico.

Por eso surgen las funciones, que existen en prácticamente cualquier lenguaje de programación. Son una pieza clave para la modularización, organización, simplificación del código y creación de componentes reutilizables.

Creando nuestra primera función

Aclarado esto, voy a crear un archivo nuevo para no mezclar tantas cosas. En este caso lo llamé functions.php.

Para declarar una función en PHP, igual que antes, abrimos el bloque PHP:

<?php ?>

Y ahora sí, creamos nuestra primera función:

function hello() {
   echo "Hola";
}

Esta es la estructura básica:

  • La palabra reservada function.
  • El nombre de la función (sin espacios ni caracteres especiales).
  • Los paréntesis.

Las llaves que contienen el código reutilizable.

Como nota: no puedes usar nombres reservados como variables (aunque en PHP sí puedes usar $function porque todas las variables llevan $, pero en otros lenguajes no).

Si intentas llamar una función que no existe, obtendrás un error. Pero mientras solo esté declarada y no se invoque, no pasará nada.

Para invocarla, simplemente haces:

hello();

Uso de parámetros

Vamos ahora con otra parte importante: los parámetros.

Diseñemos una función que reciba un nombre:

function hello($name) {
   echo "Hola " . $name;
}

Si la llamas sin parámetros, PHP indicará que la función esperaba uno, pero recibió cero.
Para usarla correctamente:

hello("Andrés");

Los parámetros simplemente representan los datos que necesita la función para ejecutar su propósito.

Una función con varios parámetros

Supongamos ahora una función de suma:

function sum($a, $b) {
   echo $a + $b;
}

La llamamos así:

sum(5, 10);

Hasta aquí imprime el resultado, pero no retorna nada. Esto se vuelve problemático cuando queremos usar el valor calculado fuera de la función.

Retornando valores

Si queremos que la función “devuelva” algo para reutilizarlo, usamos return:

function sum($a, $b) {
   return $a + $b;
}

Ahora sí podemos hacer:

$resultado = sum(5, 10);
var_dump($resultado);

Esto te devuelve el tipo y valor, gracias a var_dump.

Tipos de datos en argumentos

Otro detalle importante: si no declaras tipos, PHP intentará convertir los valores automáticamente, lo cual puede generar errores silenciosos.
Por ejemplo, podrías pasar un string donde se esperaba un número.

Para evitarlo, puedes tipiar así:

function sum(int $a, int $b) {
   return $a + $b;
}

Si llamas:

sum("hola", 5);

Ahora el error será claro: el argumento no cumple el tipo.

También puedes permitir múltiples tipos:

function sum(int|float $a, int|float $b) {
   return $a + $b;
}

Declarando el tipo de retorno

Además del tipo de los argumentos, también puedes tipar el valor que retornará la función:

function sum(int $a, int $b): int {
   return $a + $b;
}

Esto da más consistencia y seguridad al código.

Si la función retornara strings, por ejemplo, simplemente indicarías : string.

Otros aspectos útiles

PHP también soporta:

  • funciones variádicas (function test(...$args)),
  • funciones flecha (fn($a) => $a * 2),
  • y muchas funciones internas como var_dump, gettype, etc.
  • En general, con esto ya tienes:
  • Cómo declarar funciones,
  • Cómo invocarlas,
  • Cómo usar parámetros,
  • Cómo retornar valores,
  • Cómo usar tipos de datos en parámetros y retornos.

🧠 Estructuras de Control: El Uso de Condicionales

1. Concepto Básico: ¿Qué es un Condicional?

Un condicional es simplemente una estructura de control que permite tomar decisiones en base a una condición booleana (verdadero o falso). Es el equivalente a las estructuras if y else que existen en la mayoría de los lenguajes de programación.

Ejemplo: ¿Tu edad es mayor a 18? (Verdadero o Falso).

2. Operadores de Comparación

Para establecer una condición, empleamos operadores de comparación:

Igualdad estricta (==): Compara si dos valores son iguales. (Diferente a la asignación simple: $edad = 18;).

  • Mayor que (>): $edad > 18
  • Menor que (<): $edad < 18
  • Mayor o igual que (>=): $edad >= 18
  • Menor o igual que (<=): $edad <= 18
  • Distinto de (!= o <>)

Ejemplo Práctico: Validación de Edad

Consideremos la validación de la mayoría de edad, que en muchos lugares es a partir de los 18 años.

$edad = 18;
// Usamos el operador "Mayor o igual que" (>=) para incluir el 18
if ($edad >= 18) {
    echo "Eres mayor de edad. Felicidades, ahora tienes que trabajar.";
} else {
    echo "Eres menor de edad.";
}
  • Problema de solo > (Mayor que): Si usamos $edad > 18, el código fallará si la edad es exactamente 18, porque 18 no es mayor que 18.
  • Solución: El operador >= resuelve esto al comparar si es mayor o exactamente igual al valor especificado.

Anidando Condiciones: elseif

Cuando tenemos múltiples condiciones que son mutuamente excluyentes (es decir, solo queremos que se cumpla una de ellas), debemos anidar el código utilizando elseif.

Si no anidamos los condicionales, todos los bloques que cumplan su condición se ejecutarán, lo cual es incorrecto para la mayoría de las lógicas (como determinar un rango de notas).

🎓 Ejemplo de Notas (Lógica Excluyente)

Queremos evaluar si una persona es excelente, buena o necesita mejorar, basándonos en rangos:

  • Excelente: Mayor o igual a 90.
  • Bueno: Mayor o igual a 70.
  • Necesita Mejorar: Menor a 70.
$nota = 75;
if ($nota >= 90) {
    echo "Eres excelente."; // Si entra aquí, ignora el resto
} elseif ($nota >= 70) {
    echo "Eres bueno. Un promedio como todo en tu vida."; // Si entra aquí, ignora el 'else'
} elseif ($nota >= 50) {
    echo "Necesitas mejorar.";
} else {
    echo "Eres un zapacuco."; // Si no se cumplió ninguna de las anteriores
}

Ventaja del elseif: PHP evalúa el primer if. Si es true, ejecuta el bloque y sale de toda la estructura. Si es false, pasa al siguiente elseif y repite el proceso. Esto asegura que solo se ejecute un único bloque de código, garantizando la lógica correcta.

Ejemplo con 75:

  • $nota >= 90 (75 >= 90) - Falso.
  • elseif ($nota >= 70) (75 >= 70) - Verdadero. - Ejecuta y sale.

⚙️ Estructuras de Control: El uso de switch

El switch es otra estructura de control que, si bien es similar al if/else, ofrece una implementación más limpia y pensada para la evaluación de múltiples casos.

1. ❓ El Problema de las Múltiples Condiciones

Aunque el if/else funciona para cualquier evaluación, su legibilidad se complica cuando se necesitan cuatro, cinco o más condiciones anidadas o secuenciales.

Por ejemplo, si necesitáramos evaluar la variable nota con múltiples rangos (mayor a 90, mayor a 80, mayor a 70, etc.), la cadena de else if se vuelve densa:

if (nota > 90) {
    // ...
} else if (nota > 80) {
    // ...
} else if (nota > 70) {
    // ...
}
// ... y así sucesivamente.

Para estos escenarios, el switch es una alternativa más adecuada y fácil de leer.

2. 📝 Sintaxis Básica del switch

La estructura switch evalúa una única expresión (variable, retorno de función, etc.) contra una serie de casos predefinidos (case).

switch (condición_a_evaluar) {
   case valor1:
       // Código a ejecutar si se cumple valor1
       break;
   case valor2:
       // Código a ejecutar si se cumple valor2
       break;
   // ... más casos
   default:
       // Código a ejecutar si no se cumple ningún caso
       break;
}

Elementos Clave:

  • switch (condición): Aquí se coloca la variable o el valor que deseamos evaluar (ej: nota, dia).
  • case valor:: Define una condición específica. Nota que se utiliza dos puntos : en lugar de llaves {}.
  • break;: Esencial. Al igual que el else evita la reevaluación innecesaria en la estructura if/else, el break garantiza que, una vez que se cumple un case, el programa deje de evaluar los siguientes casos y salga inmediatamente del switch.
  • Si eliminas el break, el programa ejecutará el código de ese case y continuará ejecutando el código del siguiente case hasta encontrar un break o terminar la estructura.

3. 🎯 El Caso por Defecto (default)

El default es el equivalente del else en la estructura if/else.

  • Función: Si ninguna de las condiciones de los case se cumple, el bloque de código dentro de default siempre se ejecutará.
  • Ubicación: Por convención, se coloca siempre como el último caso a evaluar.
  • Uso: Puedes usarlo para manejar valores inesperados (ej: si esperas un día de la semana, pero el usuario ingresa "X") o para definir una acción base si el valor no coincide con ningún caso específico.

Ejemplo Práctico (Días de la Semana)

Si queremos evaluar la variable dia, un switch es perfecto para los siete días.

$dia = "Lunes";
switch ($dia) {
   case 'Lunes':
       echo "Comienza la semana."; // Entra aquí
       break;
   case 'Viernes':
       echo "Último día laboral.";
       break;
   default:
       echo "Es un día normal."; // Entra si el día es 'Martes', 'X', etc.
       // El break aquí es opcional, ya que es el último caso.
       break; 
}

Recordatorio: Las condiciones de los case se evalúan en el orden en que están dispuestos. Es crucial que el orden tenga sentido para la lógica de tu aplicación.

4. 🚀 Consejos para Práctica

Para familiarizarte con el switch, te recomiendo:

  • Piensa en la Lógica: Crea un escenario de negocio (ej: manejar estados de un pedido, asignar categorías a puntuaciones).
  • Implementa el switch: Escribe la estructura para ese escenario.
  • Convierte y Compara: Utiliza herramientas de IA (como el asistente de código de tu editor) para convertir tu switch a un if/else y viceversa. Esto te ayudará a entender cómo se mapean las dos estructuras: el default siempre será el else final.

Operador Ternario ?: - Coalescing ?? y Null Safety

Vamos a explorar dos operadores muy útiles en PHP para realizar condicionales cortos y manejar la asignación de valores, especialmente cuando se trata de evitar tipos nulos.

Los dos operadores que veremos son:

  1. Operador Ternario (? :)
  2. Operador de Fusión de Nulos (Null Coalescing Operator, ??)

1. El Operador Ternario (? :)

El operador ternario es la forma más concisa de reemplazar una estructura if-else simple que realiza una asignación de valor a una variable.

Estructura Ternaria

Partimos del condicional anterior:

$edad = 5;
$mayorEdad = false; // Se inicializa para evitar nulos
if ($edad >= 18) {
   $mayorEdad = true;
} else {
   $mayorEdad = false;
}

condición      ? valor_si_true : valor_si_false   - Si la condición es verdadera, asigna el primer valor; si no, asigna el segundo.

Y el operador ternario luce como:

$edad = 20;
$mayorEdad = ($edad >= 18) ? true : false;

La ventaja principal es que permite realizar asignaciones limpias sin la necesidad de inicializar la variable antes o usar múltiples líneas de código.

2. El Operador de Fusión de Nulos (??)

Este operador (también conocido como Null Coalescing Operator) se utiliza para verificar si una variable o expresión es nula y, en caso de serlo, asignarle un valor por defecto. Es muy útil para manejar datos de entrada del usuario (como formularios) y asegurar que siempre haya un valor definido.

variable ?? valor_por_defecto - Si variable no es nula, usa su valor. Si variable es nula, usa valor_por_defecto.

$valorUsuario = null;
$valorDefecto = 10;
// Si $valorUsuario es null, asigna 10.
$resultado = $valorUsuario ?? $valorDefecto; 
// Resultado: $resultado = 10 (porque $valorUsuario es null)
// Si $valorUsuario NO es null (ej. 50), asigna 50.
$valorUsuario = 50;
$resultado = $valorUsuario ?? $valorDefecto; 
// Resultado: $resultado = 50

La Importancia de Evitar Nulos (Null Safety)

El uso de operadores como ?? está muy ligado al concepto de Null Safety (seguridad contra nulos) en la programación.

En muchos lenguajes (como JavaScript), intentar acceder a un método o propiedad de una variable que es null o undefined provoca un error fatal (una excepción).

Aunque en PHP algunas funciones de string se manejan mediante funciones de ayuda (str_lower() en lugar de $string->toLowerCase()), el ?? es esencial para evitar la ambigüedad y los errores que surgen al trabajar con referencias nulas en el flujo de la aplicación. Garantiza que la variable siempre tendrá un valor con el que trabajar.

Retos

🔹 1. Función que diga si un número es par o impar

Crear una función que reciba un número y devuelva "Par" o "Impar".

La implementación la debes de hacer mediante condicionales Y con el operador ternario (?:)

Resolución reto:

Con Condicionales
function esParOImpar($numero) {
    // 1. Validación de la data (opcional pero recomendado)
    if (!is_numeric($numero)) {
        return "El valor ingresado no es un número.";
    }
    // 2. Uso del operador módulo (%) para obtener el residuo
    // Si el residuo de la división por 2 es 0, el número es par.
    if ($numero % 2 === 0) {
        return "El número $numero es par.";
    } else {
        return "El número $numero es impar.";
    }
}

La usamos:

echo esParOImpar(10) . "<br>"; // 10 es par.
echo esParOImpar(7) . "<br>";  // 7 es impar.
echo esParOImpar("ABC") . "<br>"; // No es un número.
Con ternarios

Esta es la implementación con los ternarios:

function esParOImparTernario($numero) {
   if (!is_numeric($numero)) {
       return "El valor ingresado no es un número.";
   }
   // Usando el operador ternario para la asignación
   $res = ($numero % 2 === 0) 
       ? "El número $numero es par."  // Valor si es TRUE
       : "El número $numero es impar."; // Valor si es FALSE
       
   return $res;
   
   // Simplificación: Se puede retornar directamente
   /*
   return ($numero % 2 === 0) 
       ? "El número $numero es par." 
       : "El número $numero es impar.";
   */
}
💡 Extra: Funciones de Flecha (fn)

Aprovechando la simplificación a una sola línea, podemos refactorizar la función utilizando una Función de Flecha (fn), una característica de PHP para funciones que se definen en una sola instrucción.

La función de flecha es una forma concisa de representación. Por definición, siempre está retornando el valor de la expresión que se coloca después de la flecha, sin necesidad de usar la palabra clave return.

// Función de flecha (solo funciona si hay una única operación/expresión)
$funcionFlecha = fn($numero) => ($numero % 2 === 0) 
   ? "El número $numero es par." 
   : "El número $numero es impar.";
// Uso: Se llama a la variable como si fuera la función
echo $funcionFlecha(12) . "<br>"; // 12 es par.

Nota sobre Tipado: En las versiones modernas de PHP, se recomienda añadir firmas de tipo (argumentos y retornos) para mayor robustez y para prescindir de validaciones manuales como is_numeric().

// Función tipada
function esParOImparTipado(int $numero): string {
   // Si pasas un string, PHP fallará en la firma de la función (buena práctica)
   return ($numero % 2 === 0) 
       ? "El número $numero es par." 
       : "El número $numero es impar.";
}

Otra implementación:

$parOImparFlecha = fn(int $numero) : string => ($numero % 2 == 0) ? "El número $numero es PAR." : "El número $numero es IMPAR.";

🔹 2. Función que calcule el precio final con descuento

La función recibe un precio y un porcentaje de descuento.

Debe devolver el precio final Y un mensaje que indique el Descuento aplicado:

  • Precio inválido, si el precio NO es un numero o es negativo
  • Descuento inválido (debe ser entre 0 y 100), si descuento es mayor a 100, negativo o no es un número
  • Precio sin descuento:, Si el descuento es 0
  • Producto Gratis, si el descuento es 100
  • Precio con descuento, para el resto de los casos

La implementación se debe de realizar con condicionales y también con switch

Resolución reto:

Definimos la función y empezamos por validar la integridad de los datos. Es una buena práctica detener la ejecución tan pronto como se detecta un valor inválido.

function calcularPrecioFinal($precio, $descuento): string {
   // 1. VALIDACIÓN DEL PRECIO (Inválido o Negativo)
   // Usamos OR (||) porque con que se cumpla CUALQUIERA de las condiciones, es un error.
   if (!is_numeric($precio) || $precio < 0) {
       return "ERROR: Precio ingresado inválido o negativo.";
   }
   // 2. VALIDACIÓN DEL DESCUENTO (Inválido o Fuera de Rango 0-100%)
   if (!is_numeric($descuento) || $descuento < 0 || $descuento > 100) {
       return "ERROR: Descuento inválido. Debe estar entre 0% y 100%.";
   }
   // Nota sobre tipado: Si se define la firma con tipos (ej. (float $precio, int $descuento): string),
   // se puede omitir la comprobación is_numeric().
   
   // Formateo del precio para salida (ej. $10.00)
   $precioFormateado = number_format($precio, 2);
   
// ... (Continuación de la lógica)

Una vez que los datos son válidos (numéricos y dentro de un rango aceptable), procedemos a evaluar los casos especiales (0% y $100%).

   // 3. CASO ESPECIAL: Descuento 0%
   if ($descuento == 0) {
       return "Precio completo. Sin descuento. Total: $precioFormateado.";
   }
   // 4. CASO ESPECIAL: Descuento 100%
   if ($descuento == 100) {
       return "¡El producto es GRATIS! Total: $0.00.";
   }
   // 5. CASO GENERAL: Descuento Válido (entre 1% y 99%)
   // Si la ejecución llega a este punto, no necesitamos más comprobaciones (no es inválido, no es 0%, no es 100%).
   
   // Cálculo del precio final:
   // a) Calcular el porcentaje del descuento: descuento / 100 (ej. 50 / 100 = 0.5)
   // b) Multiplicar por el precio para obtener el monto de descuento: $precio * 0.5 = $25.00
   // c) Restar ese monto al precio base.
   $precioFinal = $precio - ($precio * ($descuento / 100));
   $precioFinalFormateado = number_format($precioFinal, 2);
   return "Precio con descuento de $descuento%. Total: $precioFinalFormateado.";
}

Probemos diferentes escenarios:

echo calcularPrecioFinal(50, 0) . "<br>";    // Sin descuento: $50.00
echo calcularPrecioFinal(100, 25) . "<br>";  // Descuento normal: $75.00
echo calcularPrecioFinal(80, 100) . "<br>"; // Gratis: $0.00
echo calcularPrecioFinal(10, -5) . "<br>";  // ERROR: Descuento inválido.
echo calcularPrecioFinal("ABC", 25) . "<br>";// ERROR: Precio inválido.

💡 Nota sobre el Uso de return

En esta función, no se utiliza la estructura else porque cada condición que maneja un caso de negocio específico utiliza la palabra clave return.

Cuando una función encuentra un return, la ejecución termina inmediatamente, sin importar el código que se encuentre después.

  • Si la función entra en el if de precio inválido, retorna el error y no ejecuta el resto del código.
  • Si la función entra en el if de descuento 0%, retorna el precio completo y no ejecuta el código del cálculo final.

Esto evita anidar múltiples if/else y hace que el flujo de la lógica sea plano y fácil de seguir.

🏗️ La Pesadilla de los Formularios en PHP

Ya, el siguiente paso viene un poco lo feo. Vamos a empezar a trabajar con los formularios. ¿Y por qué digo que viene lo feo? Porque estas son de las cosas que más me sacan de quicio en PHP: hacer un formulario en PHP puro puede implicar muchos problemas si no se organiza bien el código.

Es muy fácil terminar con programación espagueti, un montón de archivos desordenados que a la primera causan errores. Pero, de igual manera, es importante conocer cómo funciona, aunque resulte engorroso.

📝 Elementos Básicos de un Formulario HTML

Todo comienza con un formulario normal. Un formulario con su action y su method.

Método GET

Por convención (buenas prácticas), empleamos las peticiones de tipo GET para consultas.

  • Riesgo: No deberías (aunque técnicamente puedes) usar GET para crear usuarios o enviar datos sensibles, como tarjetas de crédito.
  • Motivo: Todo viaja en la URL, lo cual es extremadamente inseguro debido a las múltiples vulnerabilidades que se pueden explotar (algo que te iré explicando poco a poco a lo largo de este curso).

Método POST

La petición de tipo POST es más segura.

  • Diferencia: Ya no viaja directamente en la URL, sino como un cuerpo de la petición (algo llamado body).
  • Visualización: Esto se puede ver en el navegador al abrir las Herramientas de Desarrollador (F12) y revisar el apartado de Network (lo cual es muy útil para mis propios desarrollos).

Action y Campos del Formulario

El action (quién lo quiere procesar) es donde comienza lo fastidioso en PHP: puede ser el mismo archivo u otro archivo que quieras referenciar.

En este caso, usaremos una petición de tipo POST para simular un formulario de contacto sencillo: nombre, apellido, email y un mensaje.

  • Campos: Se utiliza un campo de texto normalito, un input (tipo text, email, etc.) o un textarea para el mensaje.
  • HTML Requerido: Es vital conocer HTML y JavaScript, por lo que asumo que tienes esos conocimientos. Puedes buscar "formularios HTML" en Google si no los tienes.
  • Nombre (name): Es importantísimo asignarle un nombre, ya que es la forma en la cual lo referenciarás desde PHP.
  • placeholder: Es un label que aparece dentro del input. Usualmente, por buenas prácticas, también se coloca una etiqueta label, pero no quiero complicar el ejercicio.
  • type="email": Las validaciones que ofrece el navegador para los campos de tipo email son excelentes; todo lo que venga de gratis, se agradece.
  • textarea: Se usa para el contenido del mensaje (un campo grande de texto) para que el usuario pueda expresarse libremente.

Quedando el formulario como:

04_formularios.php

<form action="04_formularios.php" method="POST">
    <input
        type="text"
        name="name"
        placeholder="Nombre"
        value=""
        style="width: 100%; margin-top: 5px; padding: 8px; border: 1px solid #ccc;"
    >
    <input
        type="text"
        name="surname"
        placeholder="Apellido"
        value=""
        style="width: 100%; margin-top: 5px; padding: 8px; border: 1px solid #ccc;"
    >
    <input
        type="email"
        name="email"
        placeholder="Email"
        value=""
        style="width: 100%; margin-top: 5px; padding: 8px; border: 1px solid #ccc;"
    >

    <textarea
        name="message"
        placeholder="Mensaje"
        style="width: 100%; margin-top: 5px; margin-bottom: 5px; min-height: 100px; padding: 8px; border: 1px solid #ccc;"
    ></textarea>


        <div style="display: flex; justify-content: flex-end;">
            <button
                type="submit"
                style="
                    background-color: green;
                    color: white;
                    padding: 10px 15px;
                    border: none;
                    cursor: pointer;
                    font-weight: bold;
                "
            >
                Enviar
            </button>
        </div>

</form>

Procesando datos en PHP

Para procesar los datos, usamos PHP y el arreglo $_POST:

04_formularios.php

$all_values = [
   'name' => $_POST['name'] ?? '',
   'surname' => $_POST['surname'] ?? '',
   'email' => $_POST['email'] ?? '',
   'message' => $_POST['message'] ?? ''
];
  • Usamos $_POST. Esta sintaxis ($) indica que es algo interno de PHP, y en este caso, $_POST hace referencia al método POST que definimos en el formulario HTML.
    • Por ejemplo $_POST['name'] accede al valor enviado desde el formulario.
    • Si fuera la petición configurada por GET en el formulario:
      • <form action="04_formularios.php" method="GET">
      • Sería $_POST['name'] en su lugar.
  • El operador ?? '' evita valores nulos si el usuario no envió nada.
  • Recuerda que name, surname, etc., deben coincidir con los nombres de los inputs HTML.

Lo primero que considero horrible es que una de las formas de trabajar en PHP es procesar todo en el mismo archivo. Esto lleva inevitablemente al código espagueti, ya que si es un formulario de contacto, es probable que quieras guardar los datos en la base de datos, lo que implicaría hacer la conexión y el proceso ahí mismo.

Los arrays en PHP son similares a otros lenguajes de programación. Declaramos una variable y usamos los corchetes ([]) para indicar que es un array.

Visualización de los datos

Para probar nuestro formulario, podemos usar print_r() o var_dump() en PHP, lo que nos permite ver la estructura de los datos enviados:

echo '<pre>';
print_r($all_values);
echo '</pre>';
var_dump($all_values);

Esto es útil para debugging y pruebas iniciales.

Recuerda que los datos enviados por GET aparecerán en la URL, mientras que los enviados por POST no.

😩 La Complicación de realizar el procesamiento de un formulario manualmente

El problema es que, aparte de la enorme libertad, el código que vamos a implementar es un poco complicado y difícil de leer a medida que incluyamos todas estas funcionalidades:

  • Validaciones.
  • Inyección a la base de datos.
    • Para demostrar un problema, si un usuario introduce un código malicioso, por ejemplo: <script>alert('Hakeado!')</script>
    • Se mostrará los errores por pantalla:
      • Solución: Para sanear los datos del usuario, utilizaremos la función htmlspecialchars(). Esto convierte los caracteres especiales de HTML en entidades, evitando que se ejecute código inyectado.
  • Manejo de errores.
  • Devolver el valor anterior (fíjate que, al recargar, el valor anterior se pierde, lo cual no debería pasar).

🍝 El problema del código "Spaghetti" en PHP en los formularios

Nos quedamos en este formulario y, como puedes ver, ya empezamos a tener problemas. Todo está en el mismo archivo: la lógica PHP mezclada con el HTML. Aún no hemos conectado la base de datos, ni añadido validaciones o manejo de errores, y el archivo ya se siente pesado.

Aunque podríamos intentar hacerlo modular creando carpetas y archivos, aquí radica el gran problema de PHP nativo: es tan abierto que cada programador puede organizar el proyecto como le dé la gana. Lo que para uno es lógico, para otro no lo es. Si en un proyecto así trabajan dos o tres personas, la estructura de carpetas se convierte en una locura.

Para evitar ese "libertinaje" en la organización existen los frameworks. No solo nos dan herramientas ya listas, sino que nos imponen las bases para mantener la aplicación organizada y escalable.

🔌 Conexión y Lógica de Registro

He pedido ayuda a Gemini para estructurar un ejemplo de cómo sería esta implementación de forma "tradicional" (y engorrosa). Aquí tienes un resumen de lo que sucede en el código:

  • Conexión PDO: Establecemos la conexión usando el host, usuario (root por defecto) y contraseña. Usamos un bloque try-catch para que, si la conexión falla, la aplicación no "explote" y podamos controlar el error.
  • Validación y Saneamiento: Usamos trim() para limpiar espacios en blanco y comprobamos si los campos están vacíos o si el email es válido.
  • Inserción de Datos: Escribimos la sentencia INSERT INTO de SQL. Una buena práctica es usar parámetros (como :name, :email) en lugar de meter las variables directamente, para evitar ataques de inyección SQL.

🔒 Seguridad y Caracteres Especiales

Algo vital es evitar que nos inyecten código malicioso (como un alert() de JavaScript). Para ello, usamos la función htmlspecialchars(). Esta función "escapa" los caracteres especiales (como los signos < >) para que el navegador los lea como texto plano y no como código ejecutable.

// Ejemplo de protección
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');

El código queda como:

04_formularios.php

<?php
// Configuración de la base de datos
$host     = 'localhost';
$db_name  = 'contacto_db';
$user     = 'root'; // Cambia según tu config
$password = '';     // Cambia según tu config

$errors = [];
$success_message = "";

// 1. Conexión a la base de datos con PDO
try {
    $pdo = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8", $user, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Error de conexión: " . $e->getMessage());
}

// 2. Procesar el formulario cuando se envía (POST)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    
    // Recoger y limpiar valores previos
    $name    = trim($_POST['name'] ?? '');
    $surname = trim($_POST['surname'] ?? '');
    $email   = trim($_POST['email'] ?? '');
    $message = trim($_POST['message'] ?? '');

    // 3. Validaciones
    if (empty($name))    $errors['name'] = "El nombre es obligatorio.";
    if (empty($surname)) $errors['surname'] = "El apellido es obligatorio.";
    if (empty($email)) {
        $errors['email'] = "El email es obligatorio.";
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors['email'] = "El formato de email no es válido.";
    }
    if (empty($message)) $errors['message'] = "El mensaje no puede estar vacío.";

    // 4. Si no hay errores, insertar en la BD
    if (empty($errors)) {
        try {
            $sql = "INSERT INTO mensajes (nombre, apellido, email, mensaje) VALUES (:n, :s, :e, :m)";
            $stmt = $pdo->prepare($sql);
            
            $stmt->execute([
                ':n' => $name,
                ':s' => $surname,
                ':e' => $email,
                ':m' => $message
            ]);

            $success_message = "¡Mensaje enviado y guardado correctamente!";
            
            // Limpiar campos después de éxito
            $name = $surname = $email = $message = "";
            
        } catch (PDOException $e) {
            $errors['db'] = "Error al guardar en la base de datos: " . $e->getMessage();
        }
    }
}
?>

<?php if ($success_message): ?>
    <div style="background-color: #d4edda; color: #155724; padding: 10px; margin-bottom: 10px; border: 1px solid #c3e6cb;">
        <?php echo $success_message; ?>
    </div>
<?php endif; ?>

<form action="" method="POST">
    <input
        type="text"
        name="name"
        placeholder="Nombre"
        value="<?php echo htmlspecialchars($name ?? ''); ?>"
        style="width: 100%; margin-top: 5px; padding: 8px; border: 1px solid <?php echo isset($errors['name']) ? 'red' : '#ccc'; ?>;"
    >
    <?php if(isset($errors['name'])): ?> <small style="color:red;"><?php echo $errors['name']; ?></small> <?php endif; ?>

    <input
        type="text"
        name="surname"
        placeholder="Apellido"
        value="<?php echo htmlspecialchars($surname ?? ''); ?>"
        style="width: 100%; margin-top: 5px; padding: 8px; border: 1px solid <?php echo isset($errors['surname']) ? 'red' : '#ccc'; ?>;"
    >
    <?php if(isset($errors['surname'])): ?> <small style="color:red;"><?php echo $errors['surname']; ?></small> <?php endif; ?>

    <input
        type="email"
        name="email"
        placeholder="Email"
        value="<?php echo htmlspecialchars($email ?? ''); ?>"
        style="width: 100%; margin-top: 5px; padding: 8px; border: 1px solid <?php echo isset($errors['email']) ? 'red' : '#ccc'; ?>;"
    >
    <?php if(isset($errors['email'])): ?> <small style="color:red;"><?php echo $errors['email']; ?></small> <?php endif; ?>

    <textarea
        name="message"
        placeholder="Mensaje"
        style="width: 100%; margin-top: 5px; margin-bottom: 5px; min-height: 100px; padding: 8px; border: 1px solid <?php echo isset($errors['message']) ? 'red' : '#ccc'; ?>;"
    ><?php echo htmlspecialchars($message ?? ''); ?></textarea>
    <?php if(isset($errors['message'])): ?> <small style="color:red;"><?php echo $errors['message']; ?></small> <br> <?php endif; ?>

    <div style="display: flex; justify-content: flex-end; margin-top: 10px;">
        <button
            type="submit"
            style="background-color: green; color: white; padding: 10px 15px; border: none; cursor: pointer; font-weight: bold;"
        >
            Enviar
        </button>
    </div>
</form>

⚠️ Conclusión: La pesadilla del programador primerizo
 

Como puedes ver, este archivo se ha convertido en un "todo en uno": conexión, saneamiento, validación, inserción, mensajes de éxito, errores y el formulario HTML. Esto es la definición de programación spaghetti.

Para un programador que empieza, esto puede ser frustrante. Podrías pensar: "Si esto es así de difícil, un framework será peor". Pero es todo lo contrario. Los frameworks abstraen toda esta complejidad. En los siguientes vídeos, te mostraré cómo un framework hace que todo este proceso sea mucho más limpio, seguro y, sobre todo, rápido.

¿Te gustaría que en la próxima clase te muestre la comparativa directa de este mismo código escrito en un framework para que veas cuántas líneas de código nos podemos ahorrar?

🛠️ Herramientas necesarias: Base de datos y SQL

Antes de profundizar en el código, hablemos de la infraestructura. Si no estás usando herramientas como XAMPP o WAMP, necesitarás gestionar tu base de datos manualmente.

  • DBngin (Mac/Windows): Es un programa excelente para levantar servicios de MySQL o PostgreSQL de forma sencilla. Solo tienes que agregar un nuevo servicio y seguir el asistente.
  • TablePlus: Te lo recomiendo para gestionar tus tablas visualmente. Es compatible con Windows, Mac y Linux.
  • SQL: Para que esto funcione, debemos ejecutar un script SQL que cree nuestra tabla (por ejemplo, messages). Si no conoces SQL, no te preocupes, es el lenguaje que usamos para hablar con la base de datos. Las siglas típicas como XAMPP significan: Apache, MySQL y PHP.

🛠️ Implementación y Refactorización del Formulario

He utilizado al asistente Gemini para separar la conexión en un archivo aparte llamado conexion.php. Esto es vital porque, en PHP "vanilla", vas a querer reutilizar esa misma conexión en múltiples partes del proyecto sin tener que copiar el código constantemente.

El Riesgo de “Reinventar la Rueda”

Sin embargo, modularizar manualmente tiene sus riesgos:

  1. Inconsistencia: Si dejas el proyecto cuatro semanas y vuelves, probablemente estructures los nuevos módulos de forma distinta a los anteriores.
  2. Seguridad y Visibilidad: Al importar archivos con require, todas las variables (como el host o la contraseña) quedan expuestas. Si imprimo la variable $host en el HTML, se verá sin problemas, y eso es algo que deberíamos proteger.
  3. Fragilidad: Si alguien decide cambiar el nombre de la variable de conexión (por ejemplo, de $pdo a $connect), la aplicación dejará de funcionar en todas partes donde se use, generando excepciones difíciles de rastrear.

Es por esto que insisto: no tiene sentido reinventar la rueda. Los frameworks ya ofrecen una organización excelente y solucionan problemas críticos que aquí ni siquiera hemos tocado, como la protección contra tokens CSRF.

Al usar un framework, no pierdes tiempo definiendo una estructura desde cero ni creando validaciones manuales para cada campo. PHP puro es muy propenso a generar "código espagueti" donde la lógica de negocio y el HTML están mezclados de forma defectuosa.

Cerrar ?> archivos PHP

Incluso si separamos la lógica en un archivo 04_formularios_logic.php, notarás algo curioso: en archivos que son puramente PHP, muchas veces no se utiliza la etiqueta de cierre ?>. Esto se hace para evitar que espacios en blanco accidentales al final del archivo causen errores con las cabeceras (headers) de la página:

conexion.php

<?php
// Configuración de la base de datos
$host     = 'localhost';
$db_name  = 'contacto_db';
$user     = 'root'; // Cambia según tu config
$password = '';     // Cambia según tu config

// 1. Conexión a la base de datos con PDO
try {
    $pdo = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8", $user, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Error de conexión: " . $e->getMessage());
}

04_formularios_logic.php

<?php
$errors = [];
$success_message = "";

// 2. Procesar el formulario cuando se envía (POST)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

   ***
}

04_formularios.php

<?php
require_once 'conexion.php';
require_once '04_formularios_logic.php';
?>

<form action="" method="POST">
    ***
</form>

Acepto recibir anuncios de interes sobre este Blog.

Aprende PHP desde cero con esta guía completa. Cubrimos variables, funciones, condicionales (if/else, switch) y buenas prácticas para evitar el código espagueti. ¡Prepara tus bases para dominar frameworks como Laravel!

Algunas recomendaciones:

Benjamin Huizar Barajas

Laravel Legacy - Ya había tomado este curso pero era cuando estaba la versión 7 u 8. Ahora con la ac...

Andrés Rolán Torres

Laravel Legacy - Cumple de sobras con su propósito. Se nota el grandísimo esfuerzo puesto en este cu...

Cristian Semeria Cortes

Laravel Legacy - El curso la verdad esta muy bueno, por error compre este cuando ya estaba la versi...

Bryan Montes

Laravel Legacy - Hasta el momento el profesor es muy claro en cuanto al proceso de enseñanza y se pu...

José Nephtali Frías Cortés

Fllask 3 - Hasta el momento, están muy claras las expectativas del curso

| 👤 Andrés Cruz

🇺🇸 In english

Por aquí tienes el listado completo de clases que vamos a cubrir en el libro y curso: