Guía completa de PHP 8 para desarrolladores backend

php Guía completa de PHP 8 para desarrolladores backend

Guía completa de PHP 8 para desarrolladores backend

Esta guía recoge lo esencial y práctico para llevar tus proyectos backend en PHP 8 a producción: novedades del lenguaje, buenas prácticas, seguridad, rendimiento y un ejemplo completo mínimo de API REST. Ve al grano: ejemplos de código, estructura de proyecto y por qué se hacen las cosas así.

1. ¿Qué trae PHP 8 que debes aprovechar?

  • Tipado mejorado: union types, typed properties y tipos de retorno que mejoran la calidad y autocompletado.
  • constructor property promotion: evita boilerplate en constructores.
  • match expression: más seguro y expresivo que switch.
  • Nullsafe operator (?->): evita chequeos redundantes de null.
  • Atributos (Attributes): metadatos nativos, útiles para frameworks y validaciones.
  • JIT: puede ayudar en ciertos escenarios CPU-bound, pero no es panacea para I/O-bound apps típicas.

2. Principios y mejores prácticas (rápido)

  • Usa strict_types=1 en archivos sensibles para evitar coerción sorpresa.
  • Sigue PSR (PSR-12 formateo, PSR-4 autoloading); facilita colaboración y tooling.
  • Dependencias con Composer; evita commits de vendor/.
  • Preferir DI (Dependency Injection) sobre singletons/globals.
  • Escribe tests (unitarios/integración) y CI para pipelines automatizados.

3. Seguridad crítica

  • SQL injection: usa siempre sentencias preparadas (PDO/Doctrine) y evita concatenar input en consultas.
  • Validación y saneamiento: valida en la capa de entrada, no confíes en el cliente.
  • Contraseñas: password_hash() y password_verify(); nunca md5/sha1.
  • Escape de salida: htmlspecialchars() al renderizar; JSON con json_encode() correctamente configurado (JSON_UNESCAPED_UNICODE cuando convenga).
  • Headers de seguridad: Content-Security-Policy, X-Frame-Options, Strict-Transport-Security (HSTS).

4. Rendimiento y despliegue

  • Activa OPcache (config en php.ini). Esto siempre mejora latencia.
  • JIT: habilítalo solo si tu app tiene hotspots CPU-bound y tras medir. No esperes mejora en la mayoría de apps I/O.
  • Caching: aplica caching a resultados pesados (Redis, Memcached) y considera HTTP cache headers.
  • Usa un pool de conexiones DB en procesos persistentes (p. ej. PHP-FPM con PDO persistent cuando convenga).
  • Containeriza (Docker) y orquesta (Kubernetes) solo cuando lo necesites; instrumenta con métricas y traces (Prometheus, Jaeger).

5. Manejo de errores y observabilidad

  • No suprimir errores en producción; loguea con nivel adecuado. Usa Monolog y envía errores críticos a un Sentry u otra plataforma.
  • Preferir excepciones tipadas; captura y transforma a respuestas HTTP coherentes en el gateway.
  • Instrumenta timelines de requests y long-tails para detectar latencias fuera de lo común.

6. Estructura mínima recomendada para un proyecto backend

Una estructura simple, clara y compatible con PSR-4:

project/
├─ src/
│  ├─ Controller/
│  ├─ Repository/
│  ├─ Service/
│  └─ Kernel.php
├─ public/
│  └─ index.php
├─ config/
│  └─ database.php
├─ tests/
├─ composer.json
└─ Dockerfile

7. Tutorial práctico mínimo: API REST de usuarios (SQLite + PDO)

Objetivo: un endpoint GET /users que devuelva JSON. Implementación mínima sin frameworks para mostrar DI, prepared statements y buenas prácticas.

composer.json

{
  "name": "example/php8-api",
  "require": {
    "php": "^8.0",
    "ext-pdo": "*",
    "monolog/monolog": "^3.0"
  },
  "autoload": {
    "psr-4": { "App\\": "src/" }
  }
}

config/database.php

<?php
return [
    'driver' => 'sqlite',
    'database' => __DIR__ . '/../data/app.sqlite',
];

src/Repository/UserRepository.php

<?php
declare(strict_types=1);

namespace App\Repository;

use PDO;

class UserRepository
{
    public function __construct(private PDO $pdo) {}

    /**
     * @return array>
     */
    public function all(): array
    {
        $stmt = $this->pdo->query('SELECT id, username, email FROM users');
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
}

src/Controller/UserController.php

<?php
declare(strict_types=1);

namespace App\Controller;

use App\Repository\UserRepository;

class UserController
{
    public function __construct(private UserRepository $repo) {}

    public function index(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($this->repo->all(), JSON_UNESCAPED_UNICODE);
    }
}

public/index.php

<?php
declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';

use App\Repository\UserRepository;
use App\Controller\UserController;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// Simple bootstrap / DI
$config = require __DIR__ . '/../config/database.php';

$logger = new Logger('app');
$logger->pushHandler(new StreamHandler(__DIR__ . '/../logs/app.log', Logger::DEBUG));

$pdo = new PDO("sqlite:" . $config['database']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$userRepo = new UserRepository($pdo);
$controller = new UserController($userRepo);

// Very minimal router
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];

if ($path === '/users' && $method === 'GET') {
    $controller->index();
    exit;
}

http_response_code(404);
echo json_encode(['error' => 'Not found']);

Crear base de datos de ejemplo

-- script: data/init.sql
CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, email TEXT NOT NULL);
INSERT INTO users (username, email) VALUES ('alice', 'alice@example.com'), ('bob', 'bob@example.com');

-- Crear DB desde línea de comandos:
-- sqlite3 data/app.sqlite < data/init.sql

8. Por qué esta arquitectura y decisiones

  • PSR-4 y autoload facilitan testing y escalado del código.
  • PDO + prepared statements protegen contra inyección SQL y funcionan con múltiples DBs.
  • Separación Repo / Controller permite swap de capas (por ejemplo, reemplazar SQLite por MySQL o un ORM) sin tocar controladores.
  • Monolog ofrece logging estructurado; útil para enviar a sistemas externos en producción.

9. Checklist antes de producción

  • Configurar OPcache y parámetros de PHP-FPM (pm.max_children, etc.).
  • Bloquear display_errors en producción y usar logs centralizados.
  • Habilitar HTTPS y asegurar cabeceras HTTP.
  • Agregar rate limiting y protección contra CSRF si hay formularios o sesiones.
  • Revisar dependencias con Composer audit / herramientas de seguridad.

10. Herramientas recomendadas

  • Static analysis: PHPStan o Psalm (subir el nivel progresivamente)
  • Formatter: PHP CS Fixer o phpcs con reglas PSR-12
  • Profiling: Xdebug (local), Blackfire o Tideways (producción)

Consejo avanzado: integra PHPStan/ Psalm en tu CI para bloquear merges con errores estáticos y configura thresholds incrementales. Advertencia: medir primero antes de habilitar JIT en producción; su mejora depende fuertemente del tipo de carga. Siguiente paso: implementa autenticación basada en tokens (JWT o introspección con OAuth2) y añade pruebas de integración para tus endpoints.

Comentarios
¿Quieres comentar?

Inicia sesión con Telegram para participar en la conversación


Comentarios (0)

Aún no hay comentarios. ¡Sé el primero en comentar!

Iniciar Sesión