Diferencia entre revisiones de «PHP Paso de datos na URL»
Ir a la navegación
Ir a la búsqueda
| (No se muestran 5 ediciones intermedias del mismo usuario) | |||
| Línea 1: | Línea 1: | ||
| − | + | == Paso de datos pola URL == | |
| − | * | + | * Unha forma de pasar información dunha páxina a outra é a través dunha [https://es.wikipedia.org/wiki/Localizador_de_recursos_uniforme URL]. |
| − | |||
| − | |||
| − | * ''' | + | * Cando unha URL leva datos despois do carácter '''?''', estes datos forman a denominada '''cadea de consulta''' ou ''query string''. |
| − | :* | + | : Por exemplo: |
| − | :* | + | |
| − | :* O usuario pode | + | ::<syntaxhighlight lang="text"> |
| − | :* | + | https://exemplo.test/buscar.php?q=php&idioma=gl |
| + | </syntaxhighlight> | ||
| + | |||
| + | : Os datos que aparecen despois do signo '''?''' son parámetros: | ||
| + | |||
| + | ::<syntaxhighlight lang="text"> | ||
| + | q=php&idioma=gl | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : O formato xeral é: | ||
| + | |||
| + | ::<syntaxhighlight lang="text"> | ||
| + | parametro1=valor1¶metro2=valor2 | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | * 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:''' | * '''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 [https://www.php.net/manual/es/reserved.variables.get.php $_GET]. | ||
| + | : Por exemplo, para unha URL: | ||
| − | + | ::<syntaxhighlight lang="text"> | |
| + | detalle.php?pelicula=SUPERMAN | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : podemos obter o valor mediante: | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $pelicula = $_GET['pelicula'] ?? ''; | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : Empregamos o operador '''??''' para proporcionar un valor por defecto no caso de que o parámetro non exista. | ||
| + | |||
| + | <br /> | ||
| − | + | === Exemplo básico === | |
'''Arquivo: UD3_paso_var_Ex1_eleccion_pelicula.php''' | '''Arquivo: UD3_paso_var_Ex1_eleccion_pelicula.php''' | ||
| − | |||
| − | |||
| − | |||
| − | <html> | + | ::<syntaxhighlight lang="php" line enclose="div"> |
| − | + | <!DOCTYPE html> | |
| − | + | <html lang="gl"> | |
| − | + | <head> | |
| − | + | <meta charset="UTF-8"> | |
| − | + | <title>Elección dunha película</title> | |
| − | + | </head> | |
| − | + | <body> | |
| − | + | ||
| − | + | <p> | |
| + | Mandamos un nome de película fixo na URL: | ||
| + | <a href="UD3_paso_var_Ex1_datos_pelicula.php?pelicula=SUPERMAN">PELÍCULA</a> | ||
| + | </p> | ||
| + | |||
| + | </body> | ||
</html> | </html> | ||
| − | </syntaxhighlight> | + | </syntaxhighlight> |
| + | '''Arquivo: UD3_paso_var_Ex1_datos_pelicula.php''' | ||
| − | + | ::<syntaxhighlight lang="php" line enclose="div"> | |
| − | ::<syntaxhighlight lang="php" line enclose="div | + | <?php |
| − | < | + | $peliculaRecibida = $_GET['pelicula'] ?? ''; |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | if (!is_string($peliculaRecibida)) { | |
| + | $peliculaRecibida = ''; | ||
| + | } | ||
| − | + | $pelicula = trim($peliculaRecibida); | |
| + | ?> | ||
| + | <!DOCTYPE html> | ||
| + | <html lang="gl"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"> | ||
| + | <title>Datos da película</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <p> | ||
| + | A película pasada como parámetro na URL é: | ||
| + | <strong><?= htmlspecialchars( | ||
| + | $pelicula, | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ) ?></strong> | ||
| + | </p> | ||
| − | + | </body> | |
| − | |||
</html> | </html> | ||
| − | </syntaxhighlight> | + | </syntaxhighlight> |
| + | * 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'''. |
| + | |||
| + | <br /> | ||
== Pasando caracteres especiais na URL == | == 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 | + | * Para codificar '''un valor individual''' podemos empregar a función [https://www.php.net/manual/es/function.urlencode.php urlencode]. |
| − | : | + | : Exemplo: |
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $pelicula = urlencode('E.T. El extraterrestre'); | ||
| + | |||
| + | echo "<a href='detalle.php?pelicula=$pelicula'>PELÍCULA</a>"; | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : Neste caso o espazo en branco codifícase como '''+'''. | ||
| + | |||
| + | * Para realizar a operación inversa existe [https://www.php.net/manual/es/function.urldecode.php 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. | ||
| + | |||
| + | <br /> | ||
| + | |||
| + | === 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 [https://www.php.net/manual/es/function.http-build-query.php http_build_query()], que xera unha cadea de consulta correctamente codificada a partir dun array. | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $parametros = [ | ||
| + | 'pelicula' => 'E.T. El extraterrestre', | ||
| + | 'xenero' => 'Ciencia ficción' | ||
| + | ]; | ||
| + | |||
| + | $query = http_build_query($parametros); | ||
| + | |||
| + | $url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | * Se a URL vai ser inserida posteriormente dentro de HTML, tamén debemos escapar o seu valor para o contexto HTML: | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | <a href="<?= htmlspecialchars( | ||
| + | $url, | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ) ?>">PELÍCULA</a> | ||
| + | </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 /> | ||
| + | |||
| + | === Exemplo con espazos no nome da película === | ||
'''Arquivo: UD3_paso_var_Ex1_eleccion_pelicula.php''' | '''Arquivo: UD3_paso_var_Ex1_eleccion_pelicula.php''' | ||
| − | |||
| − | |||
| − | |||
| − | <html> | + | ::<syntaxhighlight lang="php" line enclose="div"> |
| − | + | <?php | |
| − | + | $parametros = [ | |
| − | + | 'pelicula' => 'E.T. El extraterrestre' | |
| − | + | ]; | |
| − | + | ||
| − | + | $query = http_build_query($parametros); | |
| − | + | ||
| − | + | $url = 'UD3_paso_var_Ex1_datos_pelicula.php?' . $query; | |
| − | + | ?> | |
| − | + | <!DOCTYPE html> | |
| − | + | <html lang="gl"> | |
| + | <head> | ||
| + | <meta charset="UTF-8"> | ||
| + | <title>Elección dunha película</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | |||
| + | <p> | ||
| + | Mandamos un nome de película na URL: | ||
| + | <a href="<?= htmlspecialchars( | ||
| + | $url, | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ) ?>">PELÍCULA</a> | ||
| + | </p> | ||
| + | |||
| + | </body> | ||
</html> | </html> | ||
| − | </syntaxhighlight> | + | </syntaxhighlight> |
| + | '''Arquivo: UD3_paso_var_Ex1_datos_pelicula.php''' | ||
| − | + | ::<syntaxhighlight lang="php" line enclose="div"> | |
| − | ::<syntaxhighlight lang="php" line enclose="div | + | <?php |
| − | < | + | $peliculaRecibida = $_GET['pelicula'] ?? ''; |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | if (!is_string($peliculaRecibida)) { | |
| + | $peliculaRecibida = ''; | ||
| + | } | ||
| − | + | $pelicula = trim($peliculaRecibida); | |
| − | + | ?> | |
| + | <!DOCTYPE html> | ||
| + | <html lang="gl"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"> | ||
| + | <title>Datos da película</title> | ||
| + | </head> | ||
| + | <body> | ||
| − | ?> | + | <p> |
| − | + | A película pasada como parámetro na URL é: | |
| + | <strong><?= htmlspecialchars( | ||
| + | $pelicula, | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ) ?></strong> | ||
| + | </p> | ||
| + | |||
| + | </body> | ||
</html> | </html> | ||
| − | </syntaxhighlight> | + | </syntaxhighlight> |
| + | |||
| + | * A URL xerada será similar a: | ||
| + | |||
| + | ::<syntaxhighlight lang="text"> | ||
| + | UD3_paso_var_Ex1_datos_pelicula.php?pelicula=E.T.%20El%20extraterrestre | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | * O usuario visualizará: | ||
| + | |||
| + | ::<syntaxhighlight lang="text"> | ||
| + | E.T. El extraterrestre | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | <br /> | ||
| + | |||
| + | === urlencode(), rawurlencode() e urldecode() === | ||
| + | |||
| + | * [https://www.php.net/manual/es/function.urlencode.php urlencode()] codifica unha cadea segundo o formato empregado habitualmente nas cadeas de consulta. Os espazos convértense en '''+'''. | ||
| + | |||
| + | * [https://www.php.net/manual/es/function.rawurlencode.php rawurlencode()] emprega unha codificación conforme á RFC 3986. Os espazos convértense en '''%20'''. | ||
| + | |||
| + | * [https://www.php.net/manual/es/function.urldecode.php urldecode()] realiza a operación inversa de urlencode(). | ||
| + | |||
| + | : Exemplo: | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $cadea = 'Espero que isto se lea ben'; | ||
| + | |||
| + | $cadeaCodificada = urlencode($cadea); | ||
| + | |||
| + | echo $cadeaCodificada; | ||
| + | echo '<br>'; | ||
| + | echo urldecode($cadeaCodificada); | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : Resultado: | ||
| + | |||
| + | ::<syntaxhighlight lang="text"> | ||
| + | Espero+que+isto+se+lea+ben | ||
| + | Espero que isto se lea ben | ||
| + | </syntaxhighlight> | ||
| + | <br /> | ||
| − | + | == 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: | ||
| − | + | ::<syntaxhighlight lang="text"> | |
| − | ::<syntaxhighlight lang=" | + | Código - Nome - Descrición |
| − | + | 1 - Tomates - Tomates da horta. Ecolóxicos... | |
| − | + | 2 - Coliflor - Coliflor da horta. Ecolóxica... | |
| − | + | </syntaxhighlight> | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | * Na páxina que amosa a lista de produtos poderiamos construír enlaces como: | |
| − | + | ::<syntaxhighlight lang="html"> | |
| − | + | <a href="detalleProduto.php?codigo=1">Tomates</a> | |
| − | + | <a href="detalleProduto.php?codigo=2">Coliflor</a> | |
| − | + | </syntaxhighlight> | |
| − | + | ||
| − | </ | + | * 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: | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $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.'); | ||
| + | } | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | * Posteriormente poderiamos realizar a consulta á base de datos empregando '''PDO e unha consulta preparada''': | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | $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.'); | ||
| + | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| − | : | + | * Ao amosar os datos en HTML escaparemos aqueles valores que poidan conter texto: |
| − | ::<syntaxhighlight lang="php" | + | |
| − | + | ::<syntaxhighlight lang="php"> | |
| − | + | <h2><?= htmlspecialchars( | |
| + | $produto['nome'], | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ) ?></h2> | ||
| + | |||
| + | <p><?= htmlspecialchars( | ||
| + | $produto['descricion'], | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ) ?></p> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | * '''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. | ||
| + | <br /> | ||
| − | + | == Paso de datos con Location == | |
| − | |||
| + | * Podemos redireccionar o navegador mediante a cabeceira HTTP '''Location''': | ||
| − | + | ::<syntaxhighlight lang="php"> | |
| − | + | header('Location: nova_paxina.php'); | |
| − | ::<syntaxhighlight lang=" | + | exit; |
| − | |||
| − | |||
| − | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| − | * Se | + | * Se queremos enviar parámetros na redirección, é preferible construír a cadea de consulta con '''http_build_query()''': |
| − | ::<syntaxhighlight lang=" | + | |
| − | + | ::<syntaxhighlight lang="php"> | |
| − | + | $parametros = [ | |
| + | 'nome' => 'Ana', | ||
| + | 'idade' => 20 | ||
| + | ]; | ||
| + | |||
| + | $query = http_build_query( | ||
| + | $parametros | ||
| + | ); | ||
| + | |||
| + | header('Location: nova_paxina.php?' . $query); | ||
| + | exit; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| − | + | * 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. | ||
| − | + | <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 == | ||
| + | : 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. | ||
| + | |||
| + | <u>Nota:</u> 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. | ||
| + | |||
| + | <br /> | ||
| + | |||
| + | === Solución do exercicio proposto === | ||
| + | |||
| + | ==== Páxina alta_alumno.php ==== | ||
| + | |||
| + | ::<syntaxhighlight lang="php" enclose="div"> | ||
| + | <?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> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | <br /> | ||
| + | |||
| + | ==== Páxina procesar_alta.php ==== | ||
| + | |||
| + | ::<syntaxhighlight lang="php" enclose="div"> | ||
| + | <?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; | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | |||
| + | ==== Páxina xestion_alumno.php ==== | ||
| + | |||
| + | ::<syntaxhighlight lang="php" enclose="div"> | ||
| + | <?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> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | <br /> | ||
| + | |||
| + | == 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: | ||
| + | |||
| + | ::<syntaxhighlight lang="php"> | ||
| + | htmlspecialchars( | ||
| + | $dato, | ||
| + | ENT_QUOTES | ENT_SUBSTITUTE, | ||
| + | 'UTF-8' | ||
| + | ); | ||
| + | </syntaxhighlight> | ||
| + | * '''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. | ||
| − | <br> -- [[Usuario:angelfg|Ángel D. Fernández González]] -- ( | + | <br /> |
| + | -- [[Usuario:angelfg|Ángel D. Fernández González]] -- (2026). | ||
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).