Diferencia entre revisiones de «PHP Paso de datos na URL»
Ir a la navegación
Ir a la búsqueda
| (No se muestran 2 ediciones intermedias del mismo usuario) | |||
| Línea 153: | Línea 153: | ||
]; | ]; | ||
| − | $query = http_build_query( | + | $query = http_build_query($parametros); |
| − | |||
| − | |||
| − | |||
| − | |||
| − | ); | ||
$url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; | $url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| − | |||
* Se a URL vai ser inserida posteriormente dentro de HTML, tamén debemos escapar o seu valor para o contexto HTML: | * Se a URL vai ser inserida posteriormente dentro de HTML, tamén debemos escapar o seu valor para o contexto HTML: | ||
| Línea 174: | Línea 168: | ||
) ?>">PELÍCULA</a> | ) ?>">PELÍCULA</a> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | |||
| + | <br /> | ||
| + | * http_build_query tamén permite enviar como dato na url un array da forma: | ||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $errors[] = 'Un error a informar'; | ||
| + | $errors[] = 'Outro error a informar'; | ||
| + | $parametros = [ | ||
| + | 'errors' => $errors | ||
| + | ]; | ||
| + | |||
| + | $query = http_build_query($parametros); | ||
| + | |||
| + | $url = 'paxina_recibir_datos.php?' . $query; | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : E na páxina de destino: | ||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $errors = $_GET['errors'] ?? []; | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | |||
<br /> | <br /> | ||
| Línea 187: | Línea 204: | ||
]; | ]; | ||
| − | $query = http_build_query( | + | $query = http_build_query($parametros); |
| − | |||
| − | |||
| − | |||
| − | |||
| − | ); | ||
$url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; | $url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; | ||
| Línea 400: | Línea 412: | ||
$query = http_build_query( | $query = http_build_query( | ||
| − | $parametros | + | $parametros |
| − | |||
| − | |||
| − | |||
); | ); | ||
| Línea 413: | Línea 422: | ||
* Despois dunha redirección é recomendable empregar '''exit;''' para evitar que continúe a execución do script. | * Despois dunha redirección é recomendable empregar '''exit;''' para evitar que continúe a execución do script. | ||
| + | |||
| + | |||
<br /> | <br /> | ||
| + | A función http_build_query() soporta arrays anidados, polo que permite enviar un conxunto de erros directamente sen necesidade de unilos manualmente con implode(): | ||
== Exercicio proposto == | == Exercicio proposto == | ||
| Línea 463: | Línea 475: | ||
// Data máxima permitida: hoxe menos 10 anos. | // Data máxima permitida: hoxe menos 10 anos. | ||
| − | $dataMaxima = | + | $dataMaxima = date('Y-m-d', strtotime('-10 years')); |
| − | + | ||
| − | |||
?> | ?> | ||
<!DOCTYPE html> | <!DOCTYPE html> | ||
| Línea 504: | Línea 515: | ||
<label for="dataNacemento">Data de nacemento:</label> | <label for="dataNacemento">Data de nacemento:</label> | ||
<input | <input | ||
| − | + | type="date" | |
| − | + | id="dataNacemento" | |
| − | + | name="dataNacemento" | |
| − | + | max="<?= $dataMaxima ?>" | |
| − | + | required | |
| − | |||
| − | |||
| − | |||
| − | |||
> | > | ||
</div> | </div> | ||
| Línea 530: | Línea 537: | ||
<?php | <?php | ||
| − | |||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { | if ($_SERVER['REQUEST_METHOD'] !== 'POST') { | ||
header('Location: alta_alumno.php'); | header('Location: alta_alumno.php'); | ||
| Línea 541: | Línea 547: | ||
$dataRecibida = $_POST['dataNacemento'] ?? ''; | $dataRecibida = $_POST['dataNacemento'] ?? ''; | ||
| − | |||
if (!is_string($nomeRecibido)) { | if (!is_string($nomeRecibido)) { | ||
$nomeRecibido = ''; | $nomeRecibido = ''; | ||
| Línea 553: | Línea 558: | ||
$dataTexto = trim($dataRecibida); | $dataTexto = trim($dataRecibida); | ||
| − | / | + | // Validación do nome. |
| − | |||
| − | |||
| − | |||
| − | |||
if ($nome === '') { | if ($nome === '') { | ||
$erros[] = 'O nome é obrigatorio.'; | $erros[] = 'O nome é obrigatorio.'; | ||
| Línea 564: | Línea 565: | ||
} | } | ||
| − | / | + | // Validación da data de nacemento. |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
if ($dataTexto === '') { | if ($dataTexto === '') { | ||
$erros[] = 'Debe indicar unha data de nacemento.'; | $erros[] = 'Debe indicar unha data de nacemento.'; | ||
} else { | } else { | ||
| − | + | $dataNacemento = strtotime($dataTexto); | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | if ($dataNacemento === false) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
$erros[] = 'A data de nacemento non é válida.'; | $erros[] = 'A data de nacemento non é válida.'; | ||
| − | $ | + | } else { |
| − | + | // Data correspondente a hai 10 anos. | |
| − | + | $dataLimite = strtotime('-10 years'); | |
| − | + | if ($dataNacemento > $dataLimite) { | |
| − | + | $erros[] = 'O alumno debe ter polo menos 10 anos.'; | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
} | } | ||
| − | / | + | // Se hai erros, volvemos ao formulario. |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
if ($erros !== []) { | if ($erros !== []) { | ||
$query = http_build_query( | $query = http_build_query( | ||
| − | ['erros' => $erros] | + | ['erros' => $erros] |
| − | |||
| − | |||
| − | |||
); | ); | ||
| Línea 634: | Línea 593: | ||
} | } | ||
| − | / | + | // Todo correcto. |
| − | |||
| − | |||
| − | |||
| − | |||
$query = http_build_query( | $query = http_build_query( | ||
[ | [ | ||
'nome' => $nome, | 'nome' => $nome, | ||
'dataNacemento' => $dataTexto | 'dataNacemento' => $dataTexto | ||
| − | ] | + | ] |
| − | |||
| − | |||
| − | |||
); | ); | ||
| Línea 652: | Línea 604: | ||
exit; | exit; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | |||
<br /> | <br /> | ||
Revisión actual del 18:39 8 oct 2026
Sumario
Paso de datos pola URL
- Unha forma de pasar información dunha páxina a outra é a través dunha URL.
- Cando unha URL leva datos despois do carácter ?, estes datos forman a denominada cadea de consulta ou query string.
- Por exemplo:
https://exemplo.test/buscar.php?q=php&idioma=gl
- Os datos que aparecen despois do signo ? son parámetros:
q=php&idioma=gl
- O formato xeral é:
parametro1=valor1¶metro2=valor2
- Este mecanismo emprégase habitualmente co método HTTP GET.
- Características importantes dos datos enviados pola URL:
- Os valores son visibles na barra de enderezos do navegador.
- A URL pode gardarse no historial, nos favoritos ou aparecer en rexistros do servidor.
- O usuario pode modificar manualmente os parámetros.
- Polo tanto, nunca debemos considerar fiables os datos recibidos mediante $_GET.
- Non debemos empregar a URL para enviar contrasinais ou outros datos sensibles.
- A lonxitude máxima dunha URL depende do navegador, do servidor web e doutros compoñentes intermedios, polo que é recomendable manter as URL razoablemente curtas.
- Vantaxes:
- Permite pasar datos dunha páxina a outra sen necesidade dun formulario.
- As URL poden gardarse nos favoritos e compartirse.
- Resulta apropiado para operacións de consulta ou navegación que non modifican o estado da aplicación.
- En PHP os parámetros enviados na URL están dispoñibles no array superglobal $_GET.
- Por exemplo, para unha URL:
detalle.php?pelicula=SUPERMAN
- podemos obter o valor mediante:
$pelicula = $_GET['pelicula'] ?? '';
- Empregamos o operador ?? para proporcionar un valor por defecto no caso de que o parámetro non exista.
Exemplo básico
Arquivo: UD3_paso_var_Ex1_eleccion_pelicula.php
1 <!DOCTYPE html> 2 <html lang="gl"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Elección dunha película</title> 6 </head> 7 <body> 8 9 <p> 10 Mandamos un nome de película fixo na URL: 11 <a href="UD3_paso_var_Ex1_datos_pelicula.php?pelicula=SUPERMAN">PELÍCULA</a> 12 </p> 13 14 </body> 15 </html>
Arquivo: UD3_paso_var_Ex1_datos_pelicula.php
1 <?php 2 $peliculaRecibida = $_GET['pelicula'] ?? ''; 3 4 if (!is_string($peliculaRecibida)) { 5 $peliculaRecibida = ''; 6 } 7 8 $pelicula = trim($peliculaRecibida); 9 ?> 10 <!DOCTYPE html> 11 <html lang="gl"> 12 <head> 13 <meta charset="UTF-8"> 14 <title>Datos da película</title> 15 </head> 16 <body> 17 18 <p> 19 A película pasada como parámetro na URL é: 20 <strong><?= htmlspecialchars( 21 $pelicula, 22 ENT_QUOTES | ENT_SUBSTITUTE, 23 'UTF-8' 24 ) ?></strong> 25 </p> 26 27 </body> 28 </html>
- Podedes comprobar que, se modificades o valor do parámetro pelicula na URL e cargades de novo a páxina, o novo valor chegará mediante $_GET.
- IMPORTANTE: Que un valor apareza na URL non significa que sexa válido. O usuario pode modificalo libremente, polo que sempre debemos validar os datos antes de empregalos e escapar os datos cando os amosamos en HTML.
Pasando caracteres especiais na URL
- Os valores dunha URL non se poden construír simplemente concatenando calquera cadea. Determinados caracteres, como os espazos ou caracteres reservados, deben codificarse.
- Para codificar un valor individual podemos empregar a función urlencode.
- Exemplo:
$pelicula = urlencode('E.T. El extraterrestre'); echo "<a href='detalle.php?pelicula=$pelicula'>PELÍCULA</a>";
- Neste caso o espazo en branco codifícase como +.
- Para realizar a operación inversa existe urldecode.
- Normalmente non será necesario chamar manualmente a urldecode() para os parámetros recibidos mediante $_GET, xa que PHP xa realiza a decodificación da cadea de consulta.
Construíndo unha URL con http_build_query()
- Cando temos varios parámetros é preferible non construír a cadea de consulta manualmente.
- PHP dispón da función http_build_query(), que xera unha cadea de consulta correctamente codificada a partir dun array.
$parametros = [ 'pelicula' => 'E.T. El extraterrestre', 'xenero' => 'Ciencia ficción' ]; $query = http_build_query($parametros); $url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query;
- Se a URL vai ser inserida posteriormente dentro de HTML, tamén debemos escapar o seu valor para o contexto HTML:
<a href="<?= htmlspecialchars( $url, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' ) ?>">PELÍCULA</a>
- http_build_query tamén permite enviar como dato na url un array da forma:
$errors[] = 'Un error a informar'; $errors[] = 'Outro error a informar'; $parametros = [ 'errors' => $errors ]; $query = http_build_query($parametros); $url = 'paxina_recibir_datos.php?' . $query;
- E na páxina de destino:
$errors = $_GET['errors'] ?? [];
Exemplo con espazos no nome da película
Arquivo: UD3_paso_var_Ex1_eleccion_pelicula.php
1 <?php 2 $parametros = [ 3 'pelicula' => 'E.T. El extraterrestre' 4 ]; 5 6 $query = http_build_query($parametros); 7 8 $url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; 9 ?> 10 <!DOCTYPE html> 11 <html lang="gl"> 12 <head> 13 <meta charset="UTF-8"> 14 <title>Elección dunha película</title> 15 </head> 16 <body> 17 18 <p> 19 Mandamos un nome de película na URL: 20 <a href="<?= htmlspecialchars( 21 $url, 22 ENT_QUOTES | ENT_SUBSTITUTE, 23 'UTF-8' 24 ) ?>">PELÍCULA</a> 25 </p> 26 27 </body> 28 </html>
Arquivo: UD3_paso_var_Ex1_datos_pelicula.php
1 <?php 2 $peliculaRecibida = $_GET['pelicula'] ?? ''; 3 4 if (!is_string($peliculaRecibida)) { 5 $peliculaRecibida = ''; 6 } 7 8 $pelicula = trim($peliculaRecibida); 9 ?> 10 <!DOCTYPE html> 11 <html lang="gl"> 12 <head> 13 <meta charset="UTF-8"> 14 <title>Datos da película</title> 15 </head> 16 <body> 17 18 <p> 19 A película pasada como parámetro na URL é: 20 <strong><?= htmlspecialchars( 21 $pelicula, 22 ENT_QUOTES | ENT_SUBSTITUTE, 23 'UTF-8' 24 ) ?></strong> 25 </p> 26 27 </body> 28 </html>
- A URL xerada será similar a:
UD3_paso_var_Ex1_datos_pelicula.php?pelicula=E.T.%20El%20extraterrestre
- O usuario visualizará:
E.T. El extraterrestre
urlencode(), rawurlencode() e urldecode()
- urlencode() codifica unha cadea segundo o formato empregado habitualmente nas cadeas de consulta. Os espazos convértense en +.
- rawurlencode() emprega unha codificación conforme á RFC 3986. Os espazos convértense en %20.
- urldecode() realiza a operación inversa de urlencode().
- Exemplo:
$cadea = 'Espero que isto se lea ben'; $cadeaCodificada = urlencode($cadea); echo $cadeaCodificada; echo '<br>'; echo urldecode($cadeaCodificada);
- Resultado:
Espero+que+isto+se+lea+ben Espero que isto se lea ben
Paso dun identificador para consultar datos
- Un uso moi habitual dos parámetros dunha URL consiste en enviar o identificador dun elemento que queremos consultar.
- Por exemplo, poderiamos ter os seguintes produtos:
Código - Nome - Descrición 1 - Tomates - Tomates da horta. Ecolóxicos... 2 - Coliflor - Coliflor da horta. Ecolóxica...
- Na páxina que amosa a lista de produtos poderiamos construír enlaces como:
<a href="detalleProduto.php?codigo=1">Tomates</a> <a href="detalleProduto.php?codigo=2">Coliflor</a>
- Na páxina detalleProduto.php recibiremos o parámetro mediante $_GET.
- Como o código debe ser un número enteiro positivo, primeiro validaremos o dato:
$codigoRecibido = $_GET['codigo'] ?? ''; if (!is_string($codigoRecibido)) { $codigoRecibido = ''; } $codigo = filter_var( $codigoRecibido, FILTER_VALIDATE_INT, [ 'options' => [ 'min_range' => 1 ] ] ); if ($codigo === false) { die('O código do produto non é válido.'); }
- Posteriormente poderiamos realizar a consulta á base de datos empregando PDO e unha consulta preparada:
$stmt = $pdo->prepare( 'SELECT codigo, nome, descricion, url_imaxe FROM produtos WHERE codigo = :codigo' ); $stmt->execute([ 'codigo' => $codigo ]); $produto = $stmt->fetch(PDO::FETCH_ASSOC); if ($produto === false) { die('O produto non existe.'); }
- Ao amosar os datos en HTML escaparemos aqueles valores que poidan conter texto:
<h2><?= htmlspecialchars( $produto['nome'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' ) ?></h2> <p><?= htmlspecialchars( $produto['descricion'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' ) ?></p>
- IMPORTANTE: Un usuario pode cambiar manualmente o valor de codigo na URL.
- Polo tanto, se un determinado produto ou recurso só pode ser consultado por certos usuarios, ademais de validar o identificador teremos que comprobar no servidor que o usuario autenticado ten permiso para acceder a ese recurso.
- Cambiar GET por POST non soluciona este problema, xa que un usuario tamén pode manipular unha petición POST.
Paso de datos con Location
- Podemos redireccionar o navegador mediante a cabeceira HTTP Location:
header('Location: nova_paxina.php'); exit;
- Se queremos enviar parámetros na redirección, é preferible construír a cadea de consulta con http_build_query():
$parametros = [ 'nome' => 'Ana', 'idade' => 20 ]; $query = http_build_query( $parametros ); header('Location: nova_paxina.php?' . $query); exit;
- A chamada a header() debe realizarse antes de enviar contido ao navegador.
- Despois dunha redirección é recomendable empregar exit; para evitar que continúe a execución do script.
A función http_build_query() soporta arrays anidados, polo que permite enviar un conxunto de erros directamente sen necesidade de unilos manualmente con implode():
Exercicio proposto
- Vexamos un exemplo de validación de datos empregando un formulario.
- A situación é a seguinte:
- Páxina alta_alumno.php
- Recolle o nome e a data de nacemento dun alumno.
- Envía os datos a procesar_alta.php empregando o método POST.
- O nome debe ter un mínimo de 5 caracteres.
- O alumno debe ter polo menos 10 anos.
- Se se reciben erros desde procesar_alta.php, amósanse nunha lista.
- Páxina procesar_alta.php
- Comproba que a petición foi realizada mediante POST.
- Valida no servidor o nome e a data de nacemento.
- Se hai erros, redirecciona de novo a alta_alumno.php enviando os erros na URL.
- Para construír a cadea de consulta empregarase http_build_query().
- Se todo é correcto, redirecciona á páxina xestion_alumno.php enviando os datos necesarios.
- Páxina xestion_alumno.php
- Amosa o nome e a data de nacemento do alumno.
- Os valores recibidos pola URL deberán tratarse como datos non fiables e escaparse antes de amosalos en HTML.
Nota: A validación HTML do formulario mellora a experiencia do usuario, pero non substitúe a validación no servidor, xa que a petición pode ser modificada manualmente.
Solución do exercicio proposto
Páxina alta_alumno.php
<?php $erros = []; $errosRecibidos = $_GET['erros'] ?? []; if (is_array($errosRecibidos)) { foreach ($errosRecibidos as $erro) { if (is_string($erro)) { $erros[] = $erro; } } } // Data máxima permitida: hoxe menos 10 anos. $dataMaxima = date('Y-m-d', strtotime('-10 years')); ?> <!DOCTYPE html> <html lang="gl"> <head> <meta charset="UTF-8"> <title>Alta de alumno</title> </head> <body> <h2>Alta de alumno</h2> <?php if ($erros !== []) : ?> <ul> <?php foreach ($erros as $erro) : ?> <li><?= htmlspecialchars( $erro, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' ) ?></li> <?php endforeach; ?> </ul> <?php endif; ?> <form action="procesar_alta.php" method="post"> <div> <label for="nome">Nome:</label> <input type="text" id="nome" name="nome" minlength="5" required > </div> <div> <label for="dataNacemento">Data de nacemento:</label> <input type="date" id="dataNacemento" name="dataNacemento" max="<?= $dataMaxima ?>" required > </div> <button type="submit">Enviar</button> </form> </body> </html>
Páxina procesar_alta.php
<?php if ($_SERVER['REQUEST_METHOD'] !== 'POST') { header('Location: alta_alumno.php'); exit; } $erros = []; $nomeRecibido = $_POST['nome'] ?? ''; $dataRecibida = $_POST['dataNacemento'] ?? ''; if (!is_string($nomeRecibido)) { $nomeRecibido = ''; } if (!is_string($dataRecibida)) { $dataRecibida = ''; } $nome = trim($nomeRecibido); $dataTexto = trim($dataRecibida); // Validación do nome. if ($nome === '') { $erros[] = 'O nome é obrigatorio.'; } elseif (mb_strlen($nome) < 5) { $erros[] = 'O nome debe ter polo menos 5 caracteres.'; } // Validación da data de nacemento. if ($dataTexto === '') { $erros[] = 'Debe indicar unha data de nacemento.'; } else { $dataNacemento = strtotime($dataTexto); if ($dataNacemento === false) { $erros[] = 'A data de nacemento non é válida.'; } else { // Data correspondente a hai 10 anos. $dataLimite = strtotime('-10 years'); if ($dataNacemento > $dataLimite) { $erros[] = 'O alumno debe ter polo menos 10 anos.'; } } } // Se hai erros, volvemos ao formulario. if ($erros !== []) { $query = http_build_query( ['erros' => $erros] ); header('Location: alta_alumno.php?' . $query); exit; } // Todo correcto. $query = http_build_query( [ 'nome' => $nome, 'dataNacemento' => $dataTexto ] ); header('Location: xestion_alumno.php?' . $query); exit;
Páxina xestion_alumno.php
<?php $nomeRecibido = $_GET['nome'] ?? ''; $dataRecibida = $_GET['dataNacemento'] ?? ''; if (!is_string($nomeRecibido)) { $nomeRecibido = ''; } if (!is_string($dataRecibida)) { $dataRecibida = ''; } $nome = trim($nomeRecibido); $dataNacemento = trim($dataRecibida); ?> <!DOCTYPE html> <html lang="gl"> <head> <meta charset="UTF-8"> <title>Xestión do alumno</title> </head> <body> <h2>Alumno rexistrado correctamente</h2> <p> <strong>Nome:</strong> <?= htmlspecialchars( $nome, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' ) ?> </p> <p> <strong>Data de nacemento:</strong> <?= htmlspecialchars( $dataNacemento, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' ) ?> </p> <p> <a href="alta_alumno.php">Dar de alta outro alumno</a> </p> </body> </html>
Ideas importantes da unidade
- Os parámetros recibidos mediante $_GET deben considerarse sempre datos non fiables.
- Empregaremos ?? cando un parámetro pode non existir.
- Validaremos os datos segundo as regras da aplicación antes de empregalos.
- Para valores numéricos podemos empregar filtros como FILTER_VALIDATE_INT.
- Para consultas SQL empregaremos PDO e consultas preparadas; non concatenaremos directamente datos recibidos na consulta SQL.
- Para construír cadeas de consulta empregaremos preferentemente http_build_query().
- urlencode() ou rawurlencode() permiten codificar valores individuais dunha URL.
- Antes de amosar texto non fiable dentro de HTML empregaremos:
htmlspecialchars( $dato, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' );
- ENT_QUOTES fai que tamén se convertan as comiñas simples e dobres.
- ENT_SUBSTITUTE substitúe por un carácter de substitución as secuencias que non sexan válidas na codificación indicada, evitando problemas con texto mal codificado.
- O escapado HTML e a codificación dunha URL son operacións distintas:
- htmlspecialchars() prepara texto para o contexto HTML.
- urlencode(), rawurlencode() e http_build_query() preparan datos para unha URL.
- A validación realizada mediante HTML ou JavaScript non substitúe nunca a validación no servidor.
-- Ángel D. Fernández González -- (2026).