Algo que siempre me llamó la atención es cómo en los cursos de PHP (o de programación web en general para el caso), suele pasarse por alto hablar de HTTP.
Es cierto que esto puede sonar demasiado teórico y, lo admito, aburrido, sin embargo, es un conocimiento que va a aclararte muchas cosas.
Un claro ejemplo de esto es cuando te encontrás con un error como este:
PHP Warning: session_start(): Cannot start session when headers already sent
Cuando tu código dice algo como:
Hola! <?php session_start();
O también:
PHP Warning: Cannot modify header information - headers already sent
Al entrar a una página con un código como:
Hola! <?php setcookie('MyCookie','MyValue');
O
Hola! <?php header('Location: pagina2.php');
Seguramente sabrás (tal vez por experiencia o porque «así es como se hace») que las funciones session_start
, setcookie
y header
deben invocarse antes de enviar contenido al cliente, es decir:
<?php header('Location: pagina2.php'); ?> Hola!
Y así las cosas funcionan.
Pero, por supuesto que existe una razón para esto (No es que haya sido un capricho de Rasmus :)).
Para comprender qué tienen de especial estas funciones es necesario entender un poquito qué es lo que sucede cuando visitas una página web.
Más específicamente, debes saber lo básico sobre la forma en que se comunica el cliente (Tu navegador) y el servidor.
Esa comunicación se realiza siguiendo las reglas que establece el protocolo HTTP.
Cómo funciona HTTP
Lo primero que debes saber es que HTTP es un protocolo de transferencia de texto (De ahí su nombre HyperText Transfer Protocol).
La noción de hypertexto es algo anticuada pero no olvides que HTTP se diseñó a principios de la década de 1990!
Se trata de un texto que puede contener referencias a otros textos (Es decir, links).
Cuando comenzó la web, realmente era algo bastante simple.
Una vez establecida la conexión física no había mucho que pudiera hacer el cliente más que solicitar algún archivo de texto que, esperablemente, estaría presente en el disco del servidor.
Si este era efectivamente el caso, la tarea del servidor era enviar el contenido de ese archivo de vuelta al cliente.
Corría por cuenta del cliente interpretar ese texto y mostrarlo al usuario de una forma humanamente agradable (Esto sigue siendo así hasta hoy).
El flujo es algo similar a:
Pero, además del contenido del archivo (El HTML en este caso), el servidor envía algo de información adicional al cliente.
Esta información (o meta-información si se quiere) viaja al cliente a través de lo que se conoce como encabezados HTTP.
Cómo se ve un encabezdo HTTP
Los encabezados, como todo lo demás en HTTP, son cadenas de texto.
En particular, los encabezados son cadenas con un formato especial:
NOMBRE: VALOR
Si nunca viste estos encabezados te invito a que abras una nueva ventana de tu navegador (esta por ejemplo) y busques la consola del desarrollador (Si usás Chrome la vas a ver al apretar F12):
Te vas a encontrar con algo como:
Y en particular, si vas a la pestaña Network:
Vas a encontrarte con un detalle de todas las peticiones que tu browser hizo para poder mostrarte el sitio que estás viendo.
¿Me acompañás un pasito más?
Hacé click en una petición cualquiera:
Y ahí estás viendo los encabezados (Headers).
Si bajás un poquito por el panel derecho te encontrás con:
Los encabezados que el servidor le envió a tu navegador.
A partir de esta información el navegador toma ciertas decisiones, por ejemplo, acá vez que hay un encabezado que dice content-encoding: gzip
.
Ese encabezado le está diciendo al navegador que el texto que va a recibir (cuando finalicen los encabezados) corresponde al resultado de comprimir el contenido buscado, de modo que, para poder interpretarlo, primero tendrá que descomprimirlo.
Y aquí llegamos al fondo de la cuestión, la clave del misterio es que los encabezados siempre se envían antes del contenido propiamente dicho.
Qué tienen en común session_start(), setcookie() y header()
Lo que estas tres funciones tienen en común es que todas envían encabezados al cliente.
La función header
lo hace de forma explícita… de eso se trata precisamente, de enviar un encabezado arbitrario al cliente.
La función setcookie
en realidad es una especie de atajo para no escribir una expresión más compleja como:
header('Set-Cookie: MyCookie=Value');
Y la función session_start()
… bueno, es algo más complicado explicar qué hace pero internamente hace uso de setcookie
(es decir, de header()
).
La lista de encabezados HTTP (y sus funciones) son muchas, si estás con ganas de investigar podés seguir por acá.
Algo que te recomiendo conocer (al menos básicamente) son los códigos de error HTTP, algo que te va a venir muy bien si te toca desarrollar WebServices REST por ejemplo.
Y ahora sí, espero haberte aclarado algunos conceptos y que no te vuelva a sorprender un error de encabezados ya enviados 😉
- Cómo agregar una página de error 500 en un proyecto PHP - 31/10/2024
- ¿Cuántos contenedoresnecesita tu php? - 28/10/2024
- Cuál es el mejor framework PHP para hacer APIs REST - 25/10/2024
Hola Mauro. Qué tal!! Te sigo desde hace casi 2 años y tu trabajo me parece de los mejores que he visto y tus aportaciones a quienes estamos en el camino de PHP. ¿Has publicado algo o podrías recomendar respecto a cifrado de información? Me refiero a la pasarela de variables (get) y rutas del proyecto que se podrían observar en el código. Espero haberme explicado. Saludos y gracias.
Hola Eduardo!
Gracias por tu mensaje 🙂 No estoy seguro de haber comprendido tu pregunta.
Lo que publiqué por aquí es sobre cifrado de contraseñas (https://academy.leewayweb.com/cual-es-el-modo-mas-seguro-de-almacenar-passwords-en-php/), si se trata de pasar valores cifrados a través de URLs existen varios métodos.
Lo primero sería cifrar el dato y mandar el resultado del cifrado a través del método GET.
Dependiendo de qué tanta seguridad necesites se decidirá el mecanismo específico. Los mejores son aquellos de clave pública/clave privada, para ello te puede venir bien usar este paquete: https://github.com/defuse/php-encryption
Espero haberte ayudado 🙂