Kodokon kodokon.com

Archivos: leer, escribir, subir, JSON

Lee y escribe archivos, registra eventos, acepta subidas de forma segura y almacena tus datos como JSON.

10 min · 3 preguntas

Abrir esta lección en Kodokon

Leer un archivo requiere una sola función: file_get_contents() devuelve todo el contenido como una cadena, file() lo divide en un array de líneas. Antes de leer, comprueba el acceso con is_readable(): una ruta rota devolvería false junto con un aviso.

PHP
<?php

declare(strict_types=1);

$path = __DIR__ . '/notes.txt';

if (!is_readable($path)) {
    exit("File not found or unreadable.");
}

$content = (string) file_get_contents($path);
echo nl2br(htmlspecialchars($content, ENT_QUOTES));

$lines = file(
    $path,
    FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
);
echo count($lines) . " non-empty line(s)";
Leer el mismo archivo completo y luego línea por línea.

Para escribir, file_put_contents() reemplaza todo el contenido por defecto. Dos flags cambian las cosas: FILE_APPEND añade al final en lugar de sobrescribir, LOCK_EX establece un bloqueo exclusivo para que dos peticiones simultáneas no mezclen sus escrituras. Esa es la receta para un registro de aplicación mínimo.

PHP
<?php

declare(strict_types=1);

$logFile = __DIR__ . '/app.log';

$line = sprintf(
    "[%s] New order from %s\n",
    date('Y-m-d H:i:s'),
    'alice@example.com'
);

file_put_contents(
    $logFile,
    $line,
    FILE_APPEND | LOCK_EX
);

echo "Event logged.";
Un registro de aplicación fiable en unas pocas líneas.

Las subidas de archivos merecen un cuidado especial. El formulario debe declarar enctype="multipart/form-data", luego PHP describe el archivo recibido en $_FILES. Valida todo: el código de error, el tamaño y el tipo real detectado por finfo - nunca la extensión ni el tipo anunciado por el navegador. Por último, solo move_uploaded_file() debe mover el archivo temporal.

PHP
<?php

declare(strict_types=1);

$maxSize = 2 * 1024 * 1024;
$file = $_FILES['avatar'] ?? null;

if ($file === null || $file['error'] !== UPLOAD_ERR_OK) {
    exit("No valid file received.");
}

if ($file['size'] > $maxSize) {
    exit("File too large (2 MB max).");
}

$info = new finfo(FILEINFO_MIME_TYPE);
$mime = $info->file($file['tmp_name']);
$allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png'];

if (!isset($allowed[$mime])) {
    exit("Format not allowed.");
}

$name = bin2hex(random_bytes(8));
$target = __DIR__ . '/uploads/' . $name
    . '.' . $allowed[$mime];

move_uploaded_file($file['tmp_name'], $target);
echo "Image saved.";
upload.php: tamaño, tipo real y nombre de archivo bajo control.

El formato JSON es el puente natural entre PHP y el resto del mundo: json_encode() serializa un array, json_decode() hace lo contrario. Pasa true como segundo argumento para obtener arrays asociativos, y el flag JSON_THROW_ON_ERROR para convertir un JSON mal formado en una excepción clara en lugar de un null silencioso.

PHP
<?php

declare(strict_types=1);

$path = __DIR__ . '/tasks.json';

$json = is_readable($path)
    ? (string) file_get_contents($path)
    : '[]';

$tasks = json_decode(
    $json,
    true,
    512,
    JSON_THROW_ON_ERROR
);

$tasks[] = [
    'title' => 'Review the lesson',
    'done' => false,
];

file_put_contents(
    $path,
    json_encode(
        $tasks,
        JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
    ),
    LOCK_EX
);

echo count($tasks) . " task(s) saved";
Un mini almacén de datos: leer, modificar, reescribir.

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. ¿Qué hace el flag FILE_APPEND pasado a file_put_contents()?
    • Añade el contenido al final del archivo en lugar de sobrescribirlo
    • Crea la carpeta padre si no existe
    • Bloquea el archivo durante la escritura
  2. ¿Por qué no deberías fiarte de $_FILES['avatar']['type'] para comprobar una subida?
    • Esta clave solo existe en algunos servidores
    • Solo funciona para imágenes
    • Este valor lo envía el navegador y se puede falsificar; debes detectar el tipo real con finfo
  3. ¿Qué cambia el segundo argumento true en json_decode($json, true)?
    • La decodificación lanza una excepción en caso de error
    • Los objetos JSON se convierten en arrays asociativos de PHP en lugar de objetos stdClass
    • Las claves se convierten a mayúsculas