PHP (acrónimo recursivo de "PHP: Hypertext Preprocessor") es un lenguaje de programación de código abierto, dinámicamente tipado y orientado a objetos, diseñado para el desarrollo web del lado del servidor. PHP se incrusta en HTML, se ejecuta en el servidor con intérpretes como PHP-FPM y genera la respuesta HTTP que recibe el navegador, de modo que el cliente nunca ve el código fuente.
La versión moderna del lenguaje (PHP 8.4 y posteriores) aporta property hooks, asymmetric visibility, ampliación del modificador readonly, enums, first-class callable syntax, union, intersection y DNF types, así como un compilador JIT sobre el runtime Zend que mejora el rendimiento en cargas intensivas en CPU.
Arquitectura request-response con PHP-FPM y Nginx
PHP moderno no se ejecuta como el antiguo mod_php de Apache: el modelo habitual hoy es un proceso manager FastCGI (PHP-FPM) detrás de un servidor web como Nginx o Caddy. El servidor web atiende la conexión TCP/TLS del cliente, sirve los activos estáticos y delega al gestor PHP-FPM los ficheros .php mediante el protocolo FastCGI.
flowchart LR
Cliente[Navegador / Cliente HTTP] --> LB[Nginx / Caddy]
LB -->|FastCGI| FPM[PHP-FPM: pool de workers]
FPM --> App[Aplicación PHP: index.php + Composer]
App --> DB[(MySQL / PostgreSQL)]
App --> Cache[(Redis / APCu)]
App --> FS[(Sistema de ficheros)]
FPM -->|respuesta| LB
LB -->|HTTP/2 o HTTP/3| Cliente
Cada petición entra por el front controller (public/index.php), Composer registra los autoloaders y la aplicación resuelve la ruta, ejecuta el controlador y devuelve la respuesta. Al terminar, el worker de PHP-FPM queda libre para la siguiente petición, con un modelo shared-nothing: la memoria no se comparte entre peticiones, lo que simplifica el modelo mental y evita clases enteras de errores de concurrencia.
Fundamentos y sintaxis moderna
El código PHP se delimita con <?php al inicio del fichero. Las variables se prefijan con $ y, desde PHP 7, se declaran tipos opcionales en parámetros y retornos. En PHP 8.4 se recomienda usar tipado estricto con declare(strict_types=1); para detectar conversiones implícitas inseguras.
<?php
declare(strict_types=1);
function calcularIVA(float $base, float $tipo = 0.21): float
{
return round($base * $tipo, 2);
}
$total = calcularIVA(100.0);
echo "IVA: {$total} EUR";
Tipos estrictos vs tipos laxos
flowchart TD
Call[Llamada: calcularIVA 100] --> Check{declare strict_types}
Check -->|=1 estricto| Strict[TypeError si el tipo no coincide]
Check -->|=0 u omitido laxo| Coerce[Conversión implícita string a float]
Strict --> Safe[Errores tempranos y trazas claras]
Coerce --> Risk[Bugs silenciosos en runtime]
En modo estricto, pasar "100" a un parámetro float lanza TypeError; en modo laxo, PHP intenta convertir. Los proyectos profesionales activan strict_types en todos los ficheros.
Programación orientada a objetos
PHP soporta POO completa: clases, interfaces, traits, enums, propiedades tipadas, readonly (ampliado en 8.4), property hooks para getters y setters virtuales, visibilidad asimétrica (public private(set)), constructor promotion y named arguments.
<?php
declare(strict_types=1);
enum EstadoPedido: string
{
case Pendiente = 'PENDIENTE';
case Enviado = 'ENVIADO';
case Entregado = 'ENTREGADO';
}
final class Pedido
{
public function __construct(
public readonly string $id,
public private(set) EstadoPedido $estado = EstadoPedido::Pendiente,
public readonly array $lineas = [],
) {}
public function confirmar(): void
{
$this->estado = EstadoPedido::Enviado;
}
}
Namespaces y autoloading PSR-4
flowchart LR
Code[new App Domain Pedido] --> Autoload[Composer autoload PSR-4]
Autoload --> Map{composer json psr-4}
Map -->|App prefix = src| Path[src/Domain/Pedido.php]
Path --> FS[(Filesystem)]
FS --> Class[Clase cargada]
Class --> Code
Composer registra el prefijo de namespace y el directorio raíz; cuando se usa una clase por primera vez, el autoloader traduce App\Domain\Pedido a src/Domain/Pedido.php y la carga sin require manuales.
Gestión de dependencias con Composer
Composer es el gestor de dependencias de facto. Declara paquetes en composer.json, resuelve versiones, genera el autoloader PSR-4 y pública el lockfile (composer.lock) para despliegues reproducibles.
flowchart LR
Dev[composer require vendor paquete] --> Json[composer.json]
Json --> Solver[Resolución de versiones]
Solver --> Lock[composer.lock]
Lock --> Vendor[vendor/]
Vendor --> Autoload[vendor/autoload.php]
Autoload --> App[Aplicación]
Dev --> CI[composer install ci/cd]
CI --> Vendor
En producción, el flujo habitual es composer install --no-dev --optimize-autoloader, que usa el lockfile para instalar las versiones exactas y genera un mapa de clases optimizado.
Persistencia con PDO
PDO (PHP Data Objects) es la capa de acceso a base de datos recomendada: ofrece una API única para MySQL, PostgreSQL, SQLite y otros motores, soporta consultas preparadas para prevenir inyección SQL y transacciones explícitas.
sequenceDiagram
participant App as Aplicación PHP
participant PDO as PDO driver
participant DB as MySQL/PostgreSQL
App->>PDO: new PDO(dsn, user, pass, options)
PDO->>DB: CONNECT
App->>PDO: prepare("INSERT ... ?")
PDO->>DB: PREPARE + placeholders
App->>PDO: execute([valor])
PDO->>DB: EXECUTE con parámetros ligados
DB-->>PDO: resultado / filas afectadas
PDO-->>App: PDOStatement
App->>PDO: beginTransaction / commit / rollBack
PDO->>DB: BEGIN / COMMIT / ROLLBACK
Buenas prácticas: activar PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, usar PDO::ATTR_EMULATE_PREPARES => false, y envolver escrituras múltiples en beginTransaction() con try/catch.
<?php
declare(strict_types=1);
$pdo = new PDO(
'mysql:host=localhost;dbname=tienda;charset=utf8mb4',
'app',
getenv('DB_PASS'),
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
],
);
$stmt = $pdo->prepare('SELECT id, nombre FROM usuarios WHERE email = :email');
$stmt->execute(['email' => $email]);
$usuario = $stmt->fetch();
Sesiones, cookies y autenticación
PHP incluye manejo nativo de sesiones HTTP mediante el superglobal $_SESSION y un identificador de sesión que viaja por cookie. Las buenas prácticas modernas: regenerar el ID en login (session_regenerate_id(true)), marcar la cookie de sesión como Secure, HttpOnly y SameSite=Lax o Strict, y almacenar hashes con password_hash() usando el algoritmo por defecto.
Seguridad
PHP moderno proporciona primitivas robustas: password_hash() / password_verify() con bcrypt o argon2, filter_var() para validación, consultas preparadas con PDO, escape contextual con htmlspecialchars() para salida HTML y CSP definida en cabeceras desde Nginx o desde la propia aplicación.
Testing con PHPUnit
El framework estándar de pruebas es PHPUnit. Se instala como dependencia de desarrollo con Composer y soporta pruebas unitarias, de integración, dobles con createMock(), data providers con atributos #[DataProvider] (PHP 8 attributes) y medición de cobertura con PCOV o Xdebug.
Ecosistema
El ecosistema de PHP incluye Composer para dependencias, PHPUnit para testing, PHPStan y Psalm para análisis estático, PHP_CodeSniffer y PHP-CS-Fixer para estilo, Laravel y Symfony como frameworks de referencia, y CMS de alcance masivo como WordPress, Drupal y Magento. Para infraestructura, la combinación PHP-FPM + Nginx/Caddy en contenedores Docker es el estándar de despliegue.
Aplicaciones
PHP es adecuado para sitios dinámicos, e-commerce, CMS, intranets, APIs REST, microservicios ligeros y cualquier backend donde el modelo shared-nothing y el arranque rápido por petición aporten valor. Combinado con Composer, PSR, PDO y PHPUnit, el lenguaje alcanza la madurez que se espera de un stack backend profesional.