Apuntes DAM

Chuleta de Desarrollo Web en Entorno Servidor

PHP 8 de servidor: sintaxis, formularios, sesiones, seguridad, POO, MVC, PDO y APIs REST.

Ponte a prueba con un simulacro

PHP básico

<?phpdeclare(strict_types=1);$nombre = "Ana";  $edad = 20;echo "Hola $nombre, tienes {$edad} años";$lista = [1, 2, 3];  $persona = ["nombre" => "Ana", "edad" => 20];foreach ($persona as $clave => $valor) { echo "$clave: $valor\n"; }function iva(float $base, int $pct = 21): float { return $base * (1 + $pct / 100); }$mensaje = match (true) { $edad >= 18 => "adulto", default => "menor" };$ciudad = $_GET["ciudad"] ?? "Sevilla";
Tema: Fundamentos de PHP

Funciones de arrays y texto

count · in_array · array_key_existsTamaño · buscar valor · buscar clave
array_map · array_filter · array_reduceTransformar · filtrar · acumular
sort · usort($a, fn($x, $y) => $x <=> $y)Ordenar (modifican el array)
array_column($filas, "nombre")Extraer una columna
implode(", ", $a) · explode(",", $s)Unir · trocear
strlen · mb_strlen · str_contains · trimTexto (mb_ para UTF-8)
json_encode · json_decode($s, true)JSON ↔ array
number_format($x, 2, ",", ".")1.234,50
Tema: Fundamentos de PHP

Formularios

if ($_SERVER["REQUEST_METHOD"] === "POST") {  $email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL);  $edad  = filter_input(INPUT_POST, "edad", FILTER_VALIDATE_INT,            ["options" => ["min_range" => 0, "max_range" => 120]]);  if (!$email) $errores["email"] = "Correo no válido";  if (!$errores) { /* guardar */ header("Location: gracias.php"); exit; }}?><input name="email" value="<?= htmlspecialchars($_POST["email"] ?? "") ?>">

Patrón PRG: tras un POST correcto, redirigir para que recargar no reenvíe el formulario.

Tema: Formularios, Sesiones y Seguridad

Sesiones y cookies

session_start();                          // antes de cualquier salidaif (password_verify($clave, $hash)) {  session_regenerate_id(true);            // evita fijación de sesión  $_SESSION["usuario"] = $id;}if (!isset($_SESSION["usuario"])) { header("Location: login.php"); exit; }session_destroy();                        // cerrar sesiónsetcookie("tema", "oscuro", ["expires" => time() + 86400 * 30,  "httponly" => true, "secure" => true, "samesite" => "Lax"]);
Tema: Formularios, Sesiones y Seguridad

Seguridad

XSSEscapar al mostrar: htmlspecialchars
Inyección SQLConsultas preparadas con PDO
CSRFToken aleatorio en sesión y en un campo oculto; comparar con hash_equals
Contraseñaspassword_hash($c, PASSWORD_DEFAULT) y password_verify
Subida de ficherosComprobar tipo y tamaño, nombre nuevo, fuera de la raíz pública
Erroresdisplay_errors = Off en producción, log_errors = On
Tema: Formularios, Sesiones y Seguridad

POO

namespace App\Modelo;class Producto implements \JsonSerializable {  public function __construct(    private readonly int $id,    private string $nombre,    private float $precio = 0.0,  ) {}  public function getNombre(): string { return $this->nombre; }  public static function desdeFila(array $f): self {    return new self((int) $f["id"], $f["nombre"], (float) $f["precio"]);  }  public function jsonSerialize(): array { return get_object_vars($this); }}

Autocarga con Composer: "autoload": {"psr-4": {"App\\": "src/"}} y require "vendor/autoload.php".

Tema: POO y el Patrón MVC

MVC

Front controllerindex.php recibe todas las peticiones
RouterRuta + método → controlador y acción
ControladorLee la petición, llama al modelo y elige la vista
ModeloDatos y reglas de negocio (con PDO)
VistaPlantilla que solo muestra, con los datos ya escapados
Tema: POO y el Patrón MVC

PDO

$pdo = new PDO("mysql:host=localhost;dbname=tienda;charset=utf8mb4", $user, $pass, [  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,  PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,]);$st = $pdo->prepare("SELECT * FROM productos WHERE categoria = :c AND precio < :p");$st->execute(["c" => $cat, "p" => $max]);$filas = $st->fetchAll();$pdo->beginTransaction();try { /* varias consultas */ $pdo->commit(); }catch (Throwable $e) { $pdo->rollBack(); throw $e; }$id = $pdo->lastInsertId();
Tema: Acceso a Datos con PDO

API REST

header("Content-Type: application/json; charset=utf-8");$metodo = $_SERVER["REQUEST_METHOD"];$datos = json_decode(file_get_contents("php://input"), true);switch ($metodo) {  case "GET":    echo json_encode($repo->todos()); break;  case "POST":   http_response_code(201); echo json_encode($repo->crear($datos)); break;  case "DELETE": $repo->borrar($id); http_response_code(204); break;  default:       http_response_code(405);}

GET leer · POST crear · PUT reemplazar · PATCH modificar · DELETE borrar. Recursos en plural: /api/productos/7.

Tema: Servicios Web y APIs REST

Laravel en una línea

Route::get('/productos', [ProductoController::class, 'index'])Ruta
php artisan make:model Producto -mcrModelo, migración y controlador
Producto::where('precio', '>', 10)->get()Eloquent
{{ $variable }} en BladeMuestra escapado
$request->validate(['email' => 'required|email'])Validación
Tema: Aplicaciones Dinámicas e Híbridas

Chuletas de otras asignaturas