🐘 Fundamentos de PHP
Sintaxis, variables, tipos, operadores, control de flujo, arrays, strings, funciones, superglobals, formularios y manejo de errores en PHP 8 explicados con ejemplos completos.
Fundamentos de PHP
PHP es un lenguaje de scripting del lado del servidor diseñado para la web. Se ejecuta en el servidor, genera HTML y se integra con bases de datos. En su versión 8 es un lenguaje moderno con tipos estrictos, expresiones poderosas y un ecosistema (Composer, Laravel, Symfony) enorme. Este artículo cubre la base completa: de los tags de apertura hasta el manejo de errores, con ejemplos ejecutables.
Sintaxis básica: tags, echo y comentarios
El código PHP se incrusta en HTML o se ejecuta como scripts puros. Todo bloque abre con <?php y cierra con ?> (opcional en archivos solo PHP; se recomienda omitirlo para evitar espacios en blanco accidentales en la salida).
<?php
// Comentario de una línea
# Otro comentario de una línea (estilo shell)
/* Comentario de varias líneas
que sigue y sigue */
echo "Hola, mundo"; // echo imprime sin retorno de carro
print "Hola"; // print devuelve 1
💡
echono es una función sino una construcción del lenguaje: admite múltiples argumentosecho "a", "b"y es más rápido quevar_dump($x)(tipo y valor) oprint_r($x)(más legible para arrays).
Variables y tipos
Las variables comienzan con $. PHP es débilmente tipado: el tipo se convierte según el contexto, pero PHP 8 permite declarar tipos en parámetros y retornos.
<?php
$nombre = "Ana"; // string
$edad = 30; // int
$precio = 19.99; // float
$activo = true; // bool
$nada = null; // null
echo "Hola $nombre"; // interpolación (comillas dobles)
echo "Hola " . $nombre; // concatenación con .
| Tipo | Descripción | Ejemplo |
|---|---|---|
int |
Enteros (64 bits) | 42 |
float |
Números de coma flotante | 3.14 |
string |
Cadenas | "hola" |
bool |
Booleano | true |
array |
Colección ordenada | [1, 2, 3] |
null |
Ausencia de valor | null |
mixed |
Cualquier tipo (PHP 8) | mixed $x |
object |
Instancia de una clase | new Usuario() |
⚠️ PHP no es estrictamente tipado por defecto:
"10" + 5devuelve15por coerción. Si quieres comparaciones y operaciones estrictas, declaradeclare(strict_types=1);como primera línea del archivo y usa===en lugar de==.
<?php
declare(strict_types=1);
function precioConIva(float $precio): float
{
return $precio * 1.21;
}
var_dump(precioConIva(100)); // float(121)
var_dump((int) "42"); // int(42) — casting explícito
💡 PHP 8.0 añadió union types (
int|string) y el tipomixed. Constrict_types=1, una función que aceptaint|stringrechazafloat, lo que hace tus APIs mucho más predecibles.
Operadores
<?php
$a = 10;
$b = 3;
echo $a + $b; // 13 (aritméticos: + - * / % **)
$a += 5; // asignación combinada; también -= *= .= etc.
echo $a == $b; // igualdad suelta (10 == "10" es true)
echo $a === $b; // identidad estricta (tipo y valor)
echo $a <=> $b; // spaceship: -1, 0 o 1
echo $a ?? $b; // fusión null: $a si no es null, si no $b
echo $x && $y; // lógicos: && || !
💡 El operador spaceship
<=>devuelve-1,0o1y es ideal para funciones de comparación enusort(). La fusión null??sustituye al patrónisset($x) ? $x : $default.
Control de flujo
if / elseif / else y match
<?php
$nota = 8.5;
if ($nota >= 9) {
echo "Sobresaliente";
} elseif ($nota >= 5) {
echo "Aprobado";
} else {
echo "Suspenso";
}
// match: expresión que devuelve valor, comparación estricta, exhaustiva
$dia = 'sábado';
$esFinDeSemana = match ($dia) {
'sábado', 'domingo' => true,
default => false,
};
💡 PHP soporta sintaxis alternativa con
:yendif, muy usada en plantillas:<?php if ($x): ?> ... <?php endif; ?>.matchadmite condiciones combinadas ('a', 'b' => ...) y sindefaultlanzaUnhandledMatchError.
Bucles
<?php
// for clásico
for ($i = 1; $i <= 5; $i++) {
echo "Vuelta $i ";
}
// foreach sobre arrays asociativos
$usuarios = ['ana' => 'Ana García', 'luis' => 'Luis Pérez'];
foreach ($usuarios as $clave => $valor) {
echo "$clave → $valor ";
}
// break y continue
for ($i = 1; $i <= 10; $i++) {
if ($i % 2 === 0) continue; // salta pares
if ($i === 7) break; // se detiene en 7
echo "$i ";
}
// while (y do-while para ejecutar al menos una vez)
$i = 1;
while ($i <= 3) {
echo $i . " ";
$i++;
}
Arrays
Los arrays son mapas ordenados: asocian claves a valores. Pueden ser indexados (claves numéricas automáticas) o asociativos.
<?php
$frutas = ['manzana', 'pera', 'uva'];
echo $frutas[0]; // manzana
$producto = [
'nombre' => 'Portátil',
'precio' => 899,
'stock' => 12,
];
echo $producto['precio']; // 899
$frutas[] = 'plátano'; // añadir al final
isset($producto['stock']); // true
// Transformaciones con funciones de orden superior
$numeros = [1, 2, 3, 4, 5];
$cuadrados = array_map(fn($n) => $n ** 2, $numeros); // [1, 4, 9, 16, 25]
$pares = array_filter($numeros, fn($n) => $n % 2 === 0); // [2, 4]
$suma = array_reduce($numeros, fn($acc, $n) => $acc + $n, 0); // 15
sort($numeros); // ordena y reindexa (modifica el original)
asort($numeros); // ordena manteniendo claves
$merge = array_merge([1, 2], [3, 4]); // [1, 2, 3, 4]
$spread = [...[1, 2], ...[3, 4]]; // spread (PHP 7.4+): igual
💡 El spread operator
...en arrays (PHP 7.4+, y con claves string en PHP 8.1+) fusiona arrays de forma concisa:$config = [...$base, ...$override];donde el último gana. En funciones se usa para variadics.
Strings
<?php
$nombre = 'Ana';
$apellido = 'García';
$completo = $nombre . ' ' . $apellido; // concatenación
echo "Hola, {$nombre} {$apellido}"; // interpolación
strlen('hola'); // 4
strtoupper('hola'); // HOLA
ucfirst('ana'); // Ana
str_replace('Ana', 'Luis', $completo); // Luis García
explode(',', 'a,b,c'); // ['a', 'b', 'c']
implode('-', ['a', 'b', 'c']); // 'a-b-c'
trim(' hola '); // 'hola'
substr('abcdef', 1, 3); // 'bcd'
str_contains($completo, 'García'); // true (PHP 8)
str_starts_with($completo, 'Ana'); // true
💡 Usa comillas simples cuando no necesites interpolación: son ligeramente más rápidas y evitan escapar caracteres. Las heredocs (
<<<EOT ... EOT) permiten bloques multilínea con interpolación.
Funciones
<?php
declare(strict_types=1);
// Tipos en parámetros y retorno, valor por defecto
function saludar(string $nombre, string $saludo = "Hola"): string
{
return "$saludo, $nombre";
}
// Variadics: número variable de argumentos
function sumarTodos(int ...$numeros): int
{
return array_sum($numeros);
}
// Arrow functions (PHP 7.4+): capturan variables por valor automáticamente
$iva = 0.21;
$conIva = fn($precio) => $precio * (1 + $iva);
// First-class callable (PHP 8.1+)
$fn = strlen(...);
echo saludar('Ana'); // Hola, Ana
echo sumarTodos(1, 2, 3, 4); // 10
echo $conIva(100); // 121
echo $fn('hola'); // 4
⚠️ Las arrow functions solo contienen una expresión y capturan el ámbito exterior automáticamente; las closures clásicas necesitan
use ($variable).
Superglobals y formularios
Las superglobals son arrays siempre disponibles, definidos por el servidor web:
| Superglobal | Contenido |
|---|---|
$_GET |
Parámetros de la query string (?id=3) |
$_POST |
Cuerpo de un formulario method="post" |
$_REQUEST |
Fusión de GET/POST/cookies (evítalo: ambiguo) |
$_SERVER |
Cabeceras, URL, IP del cliente, agente de usuario |
$_SESSION |
Datos de sesión entre peticiones |
$_COOKIE |
Cookies del cliente |
$_FILES |
Archivos subidos |
<form method="post" action="procesar.php">
<label>Nombre: <input type="text" name="nombre"></label>
<button type="submit">Enviar</button>
</form>
<?php
// procesar.php
$nombre = $_POST['nombre'] ?? 'Anónimo';
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
if ($email === false) {
echo "El email no es válido";
} else {
echo "Registro de $nombre con email $email";
}
echo $_SERVER['REQUEST_METHOD']; // POST
echo $_SERVER['REMOTE_ADDR']; // IP del cliente
session_start();
$_SESSION['usuario_id'] = 42; // persistir entre peticiones
echo $_SESSION['usuario_id']; // 42
session_destroy();
⚠️ Nunca confíes en la entrada del usuario. Todo lo que llega por
$_GETy$_POSTdebe validarse y escaparse: para HTML usahtmlspecialchars($x, ENT_QUOTES), para SQL usa consultas preparadas (PDO), nunca concatenes datos crudos.
Manejo de errores y excepciones
PHP distingue entre errores (problemas del motor: TypeError, DivisionByZeroError…) y excepciones de la aplicación (RuntimeException, InvalidArgumentException…). Ambos se capturan con try/catch, y PHP 7+ los unificó bajo la interfaz raíz Throwable.
<?php
function dividir(int $a, int $b): float
{
if ($b === 0) {
throw new InvalidArgumentException("No se puede dividir por cero");
}
return $a / $b;
}
try {
$resultado = dividir(10, 0);
echo $resultado;
} catch (InvalidArgumentException $e) {
echo "Error de validación: " . $e->getMessage();
} catch (Throwable $e) {
error_log($e->getMessage()); // TypeError, Error, Exception...
echo "Ocurrió un error inesperado";
} finally {
echo "Este bloque siempre se ejecuta";
}
💡 Con
strict_types=1, una llamada con tipo incorrecto lanzaTypeError; dividir entre cero lanzaDivisionByZeroError(PHP 8). CapturandoThrowablecubres ambos mundos. Las excepciones son encadenables:throw new DomainException("...", 0, $e);conserva el error original.
Cheatsheet
| Concepto | Sintaxis clave |
|---|---|
| Imprimir | echo, var_dump() |
| Strings | concatenar ., interpolar "$var" |
| Estricto | declare(strict_types=1), ===, !== |
| Valores opcionales | $x ?? $default |
| Comparar | <=> spaceship |
| Iterar | foreach ($arr as $k => $v) |
| Transformar | array_map, array_filter, array_reduce |
| Parámetros variables | ...$args, spread ... |
| Funciones cortas | fn($x) => expr, strlen(...) |
| Entrada del usuario | $_GET, $_POST, $_SERVER |
| Fallos | throw new ...Exception, try/catch/finally |
Para profundizar
- PHP Manual — Language Reference: la referencia oficial de tipos, operadores, arrays y funciones.
- PHP Manual — PHP tags: sintaxis básica y recomendaciones de apertura/cierre.
- PHP Manual — Superglobals: documentación completa de
$_GET,$_POST,$_SERVER, etc. - PHP Manual — Exceptions: jerarquía y buenas prácticas de manejo de errores.
- PHP The Right Way: buenas prácticas, seguridad y patrones del ecosistema PHP.
- Ruta completa: Backend con PHP.