2.3 · Inclusiones, organización y gestión de archivos

Nivel 2 · PHP y la Web

2.3Inclusiones, organización y gestión de archivos

Objetivo: Organizar su código por inclusiones (require/include, config, header/footer) y gestionar archivos (leer/escribir, subidas seguras) — evitando los fallos de inclusión y de subida.
Tiempo estimado: 11 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

Lo esencial en 30 segundos

  • Escribir una vez, incluir en todas partes: header, footer, config y funciones viven en archivos dedicados ensamblados por require/include — cero duplicación.
  • require para lo indispensable: require falla en fatal si falta el archivo (config, funciones), include se conforma con avisar — *_once evita las redefiniciones.
  • Subidas = entradas hostiles: tipo real comprobado, tamaño limitado, archivo renombrado, almacenamiento sin ejecución PHP — un PHP subido ejecutable entrega el servidor al atacante.

Minicaso hilado — Riad ordena el sitio de la asociación

El sitio de la asociación de Riad crece: el mismo menú copiado en diez páginas, la conexión a la base recopiadas en todas partes — cada modificación se vuelve un calvario. Ordena: config.php para los parámetros, header.php y footer.php para el diseño, funciones.php para las utilidades, cada página ensamblada por require. Luego añade el envío de fotos de eventos: subida tratada como una entrada hostil — tipo real comprobado, archivo renombrado, guardado sin ejecución PHP. En 2.4, fechará esas fotos con DateTime.

Continuación del hilo 2.2: el sitio de Riad pasa del apaño duplicado a una estructura limpia — y continúa en 2.4.

1. Inclusiones: escribir una vez, reutilizar en todas partes

Un sitio real comparte elementos comunes (cabecera, menú, pie de página, configuración): duplicarlos en cada archivo es tedioso e imposible de mantener. PHP ofrece las instrucciones de inclusión: include y require insertan el contenido de un archivo en otro. La diferencia: require provoca un ERROR FATAL si el archivo es inalcanzable — para archivos INDISPENSABLES (configuración, funciones esenciales); include emite un simple aviso y continúa — para archivos opcionales. Sus variantes require_once e include_once garantizan una inclusión ÚNICA (sin redefiniciones) — a menudo preferibles. Típico: header.php y footer.php incluidos en cada página, config.php requerido al inicio de los scripts. Riad modifica ahora su menú en un solo lugar. Punto de SEGURIDAD crucial: no incluir NUNCA una ruta venida de una entrada de usuario (include $_GET['page']) — es un fallo de inclusión de archivo arbitrario.

2. Organizar antes de los frameworks

Estas inclusiones fundan la organización de un proyecto «a mano»: separar el código en archivos lógicos (configuración, funciones, elementos de interfaz, páginas) y ensamblarlos — primer paso hacia una arquitectura limpia, que culminará en el MVC (sección 4-1) y el autoloading (sección 3-3). Los principios: SEPARAR según las responsabilidades, REUTILIZAR por inclusiones, SEPARAR la lógica (tratamiento, consultas) de la visualización (el HTML después), ordenar en carpetas claras (includes/, páginas, assets/, uploads/ seguro) y colocar los archivos sensibles (config con identificadores) FUERA de la raíz web. El sitio de Riad adopta esta estructura: toda página empieza con el require de la config, hace su lógica e incluye luego la visualización.

3. Archivos y subidas: leer, escribir, desconfiar

PHP LEE y ESCRIBE archivos del servidor: file_get_contents() (leer todo), file_put_contents() (escribir), fopen()/fread()/fwrite()/fclose() (por pasos, archivos grandes), file_exists(), unlink() (eliminar). El caso sensible: las subidas, archivos enviados por el usuario en $_FILES — a tratar como entradas hostiles. Las protecciones, todas juntas: COMPROBAR el tipo REAL (el contenido, no la extensión declarada, falsificable) con una lista blanca y el TAMAÑO; RENOMBRAR el archivo (nunca el nombre de usuario); guardarlo FUERA de la raíz web o en una carpeta SIN ejecución PHP — si no, un archivo PHP malicioso subido y luego llamado por URL se ejecuta y compromete el servidor; mover con move_uploaded_file() tras controlar el código de error. Las fotos de eventos de Riad siguen exactamente este protocolo.

Error frecuente de interpretación: «Comprobar la extensión del archivo subido basta — .jpg es una imagen». No. La extensión y el tipo declarado por el navegador se falsifican en una línea: un script malicioso renombrado foto.jpg pasa este control sin despeinarse. La comprobación seria se refiere al CONTENIDO real (tipo MIME detectado del lado del servidor, lista blanca estricta), combinada con el renombrado y sobre todo con el almacenamiento sin ejecución PHP — incluso un archivo tramposo se vuelve inofensivo. La regla de Riad: una subida es una entrada hostil, se trata como tal, con todas las protecciones, no solo una.
Organizar y gestionar los archivos Estructurar, proteger Inclusionesrequire (fatal) / include; *_once (única)+OrganizaciónConfig, header/footer, funciones separados+Subidas ($_FILES)Tipo/tamaño, renombrar, sin ejecución PHP No incluir nunca una ruta venida del usuario (fallo de inclusión).
Estructurar, proteger
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Riad ESCRIBE UNA VEZ: config, header, footer y funciones viven en archivos dedicados, cada página los ensambla por require — fin de la duplicación. 2) Elige la herramienta correcta: require (fatal) para lo indispensable, include para lo opcional, *_once contra las redefiniciones — y nunca una ruta venida del usuario. 3) Trata las SUBIDAS como hostiles: tipo real y tamaño comprobados, archivo renombrado, guardado sin ejecución PHP. Lección: estructurar el código por inclusiones, proteger cada archivo que entra.

🔎 Ejemplo concreto — 🔎 Ejemplo concreto — Las fotos de eventos de Riad, con seguridad

Todas las protecciones, como para las subidas de Riad:

// verificar error, tamaño, TIPO REAL (lista blanca)
$nom = bin2hex(random_bytes(8)) . '.jpg';
move_uploaded_file($_FILES['img']['tmp_name'],
  __DIR__ . '/../uploads/' . $nom);
// carpeta sin ejecución PHP

Lectura: control del contenido, renombrado aleatorio, almacenamiento sin ejecución.

Lección: no conservar nunca el nombre dado por el usuario.

Vocabulario de la sección

include / require
Insertan el contenido de un archivo en otro; require provoca un error FATAL si es inalcanzable (indispensables), include un aviso y continúa (opcionales).

Ejemplo sencillo: Riad requiere config.php al inicio de cada página.

Lo que no es: un copiar-pegar del mismo menú en diez páginas.

Reflejo: indispensable = require.

require_once / include_once
Garantizan que un archivo solo se incluye UNA vez, evitando inclusiones múltiples y errores de redefinición — a menudo preferibles.

Ejemplo sencillo: funciones.php es requerido en _once en todas las páginas de Riad.

Lo que no es: una inclusión repetida que redefine las mismas funciones.

Reflejo: archivo compartido = _once por defecto.

Organización por inclusiones
Separar el código en archivos lógicos (config, funciones, header/footer, páginas) ensamblados por inclusiones; primer paso hacia una arquitectura limpia (MVC, autoloading).

Ejemplo sencillo: El sitio de Riad: config, header/footer, páginas ensambladas.

Lo que no es: un gran archivo que mezcla lógica, consultas y HTML duplicado.

Reflejo: código duplicado = archivo a extraer e incluir.

Gestión de archivos
Leer y escribir archivos del servidor: file_get_contents, file_put_contents, fopen/fread/fwrite, file_exists, unlink.

Ejemplo sencillo: Riad lee una plantilla y escribe una exportación con file_get_contents/put_contents.

Lo que no es: una subida tratada sin ningún control.

Reflejo: archivo del servidor = comprobar existencia y derechos.

Subidas ($_FILES) — seguridad
Archivos enviados por el usuario ($_FILES): comprobar tipo real y tamaño, RENOMBRAR, guardar fuera de la raíz o sin ejecución PHP, limitar las extensiones.

Ejemplo sencillo: Cada foto de Riad es renombrada y guardada sin ejecución PHP.

Lo que no es: un archivo guardado con su nombre de origen en una carpeta ejecutable.

Reflejo: subida = entrada hostil, protocolo completo.

En la práctica — En la práctica — Organizar el código y gestionar archivos

  1. Cree header.php y footer.php e inclúyalos en varias páginas con require; cree un config.php requerido al inicio de los scripts.
  2. Comprenda la diferencia require (fatal) / include (aviso) y el interés de require_once (inclusión única).
  3. Lea y escriba un archivo (file_get_contents / file_put_contents); compruebe su existencia (file_exists).
  4. Trate una subida ($_FILES) CON SEGURIDAD: compruebe tipo real y tamaño, RENOMBRE el archivo, guárdelo en una carpeta sin ejecución PHP — y no incluya NUNCA una ruta venida del usuario.
Organiza su código por inclusiones (require/include, config, header/footer) y gestiona archivos (leer/escribir, subidas seguras) — evitando los fallos de inclusión y de subida.

Script listo para decir — explicar el orden ante la oficina asociativa (30 s)

«He ordenado el sitio: el menú y el pie de página existen en un solo ejemplar, cada página los incluye — una modificación se hace en un lugar. Y para las fotos, cada archivo está comprobado, renombrado y guardado en una carpeta donde ningún script puede ejecutarse: incluso un archivo tramposo queda inofensivo.»

Para decir mostrando una modificación del menú repercutida en todas partes al instante.

Modelo copiar-pegar — esqueleto de página ensamblada


Pequeño sitio escaparate

Cinco páginas comparten header y footer: Riad corrige el menú una vez, todo el sitio sigue.

Config protegida

Identificadores de base fuera de la raíz web, requeridos al inicio: nunca expuestos por URL, nunca en el repositorio.

Exportación de datos

La lista de miembros se escribe con file_put_contents tras file_exists: lectura y escritura controladas.

Fotos de eventos

Subidas renombradas, tipo real comprobado, carpeta sin ejecución PHP: la galería queda inofensiva.

Prudencia: Una carpeta de subidas donde PHP se ejecuta convierte cada subida en una toma de control potencial: un archivo malicioso llamado por su URL se ejecuta en su servidor (robo de datos, compromiso total). Guarde siempre las subidas fuera de la raíz web o sin ejecución PHP, y no incluya nunca una ruta venida del usuario. Esta guía da el protocolo básico — haga auditar todo sistema real de subida antes de publicarlo.

✓ Buenas prácticas

  • Separar el código en archivos lógicos y reutilizar por inclusiones.
  • Privilegiar require para archivos indispensables y *_once contra las redefiniciones.
  • Tratar las subidas con todas las protecciones (tipo real, renombrado, sin ejecución).

✗ Errores frecuentes

  • Incluir una ruta venida de una entrada de usuario (inclusión de archivo arbitrario).
  • Conservar el nombre de un archivo subido dado por el usuario.
  • Guardar las subidas en una carpeta donde PHP se ejecuta (toma de control).

Puntos clave

  • INCLUSIONES (include/require): insertar un archivo en otro para no duplicar (header, footer, config, funciones). require = fatal si es inalcanzable (indispensables); include = aviso (opcionales); *_once = inclusión única.
  • Organizar el código en archivos lógicos ensamblados por inclusiones = primer paso hacia una arquitectura limpia (antes de MVC/autoloading).
  • FALLO A EVITAR: no incluir NUNCA una ruta venida de una entrada de USUARIO (include $_GET['page']) — inclusión de archivo arbitrario.
  • GESTIÓN DE ARCHIVOS (file_get_contents/put_contents, fopen…) y sobre todo SUBIDAS ($_FILES) CON SEGURIDAD: comprobar tipo real/tamaño, RENOMBRAR, guardar sin ejecución PHP, limitar las extensiones (fuente clásica de fallos graves).

Reto 48h — aplique mañana

Factorice un proyecto real: extraiga header, footer y config en archivos incluidos por require/require_once, lógica antes de la visualización. Luego proteja una subida real: tipo real, tamaño, renombrado, carpeta sin ejecución PHP.

Lista de salida de la sección
  • Puedo explicar require frente a include y el interés de *_once.
  • Sé estructurar un proyecto (config, header/footer, lógica antes de la visualización).
  • He protegido una subida real con el protocolo completo.
Autoevaluación 1-5: ¿factorizo en lugar de duplicar?¿trato cada subida como una entrada hostil?

Preguntas frecuentes

¿Cómo organizar limpiamente un proyecto PHP «a mano» antes de usar un framework?

Apunte a la SEPARACIÓN y la REUTILIZACIÓN, contra el «código espagueti» (todo mezclado, duplicado, sin estructura). (1) SEPARAR en archivos lógicos: configuración (config.php), funciones reutilizables (o clases, nivel 3), interfaz común (header.php, footer.php), páginas (contenido específico). (2) REUTILIZAR por inclusiones: escritos una vez, incluidos en todas partes — una modificación en un solo lugar. (3) SEPARAR lógica y visualización: lógica primero (tratamiento, consultas), HTML después — el camino hacia el MVC (sección 4-1). (4) ESTRUCTURAR las carpetas: includes/, páginas, assets/, uploads/ seguro. (5) PROTEGER: archivos sensibles FUERA de la raíz web, punto de entrada único idealmente, secretos fuera del repositorio. Esta organización enseña los principios que los FRAMEWORKS formalizan (MVC, enrutado, autoloading, config, seguridad).

¿Por qué las subidas de archivos son tan sensibles en seguridad y cómo gestionarlas con seguridad?

Una subida deja que un usuario DEPOSITE un archivo en SU servidor. El peor escenario: un archivo .php malicioso subido y luego llamado por URL — el servidor lo EJECUTA y el atacante toma el control (archivos, base, todo). Otros riesgos: archivos enormes (denegación de servicio), tipos engañosos, sobrescritura. Protecciones, todas juntas: (1) NUNCA ejecución — carpeta sin PHP o FUERA de la raíz web: LA protección clave. (2) RENOMBRAR (nunca el nombre de usuario) con un nombre seguro y una extensión controlada. (3) COMPROBAR el TIPO REAL (contenido, no extensión declarada) — lista blanca. (4) LIMITAR el tamaño. (5) Validar la extensión (lista blanca). (6) Controlar el código de error de $_FILES y mover con move_uploaded_file(). En un proyecto real, prefiera las herramientas probadas de los frameworks en un tema tan crítico.

Comprueba tu comprensión

¿Cuál es LA protección clave para los archivos subidos?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 2Preguntas inéditas y más difíciles para validar tus conocimientos