8721 sujets

Développement web côté serveur, CMS

Bonjour, j'ai crée un petit formulaire où il y a un endroit un où marquer le nom d'une ville et j'aimerais que quand l'utilisateur tape le nom d'une ville (si elle existe , celles que j'ai inscrite dans ma base de données ) s'affiche la ville en lien et une fois qu'on clique dessus la ville avec le descriptif s'affichent.

Voici le code du formulaire:


<form method="post">
<p>Nom de la ville : <input type="text" name="ville_nom"
value="<?php echo $nom ?>"/></p>
<input type="hidden" name="ville_id" value="<?php echo $id ?>" />
<p><input type="submit" name="submit_form" value="valider" /></p>
</form>


Je ne sais pas où est ce que dois écrire le lien qui amène à la page "ville.php"où j'ai écris les liens des villes avec descriptif.

Cordialement
Modérateur
Bonjour,

Pour un formulaire on précise dans la balise elle-même quelle est la page qui va recevoir les données via l'attribut action. Dans votre cas cela se rapprocherait de
<form action="chemin_de_fichier/ville.php" method="post">


Ensuite votre fichier ville.php va s'occuper de récupérer les données Post et de faire la corrélation avec votre base de donnée.
Meilleure solution
J'ai bien toutes les villes qui s'affichent mais si je veux que une seul s'affiche par exemple si l'utilisateur tape Paris je voudrais qu'il y est que le lien Paris qui s'affiche pour qu'apres quand on clique dessus la ville avec le descriptif s'affiche. Pas toutes les villes.
Modérateur
J'ai peur de ne pas suivre... Non pas l'objectif qui est clair comme de l'eau de roche mais plutôt le processus que vous avez mis en place pour y arriver.
Éclairez-moi car ma chandelle est morte.
Voici le code de ma page ville.php

<!DOCTYPE html>
<html>
<head>

<?php
// 1. récupération de la variable externe


$id =(int) $_GET['id'];
// 2. connexion à la base
$mysqli = new mysqli('localhost', 'root', '', 'projet_villes');
// 3. requête.
// Concaténation de la requete avec la variable $id.
$result = $mysqli->query('SELECT ville_id, ville_nom, ville_texte FROM
villes WHERE ville_id = ' . $id );
// 4. création du nouvel array
$row = $result->fetch_array();
// 5. Affichage
$nom = $row['ville_nom'];
$texte = $row['ville_texte'];
?>
<title><?php echo $nom ?></title>
<link rel="stylesheet" type="text/css" href="style.css" />
 </head>
 <body>
 <div>
<h1><?php echo $nom ?></h1>
<p><?php echo $texte ?></p>
<?php
// 2. requête
$result = $mysqli->query('SELECT ville_id, ville_nom FROM villes');
// 3.a. transformation en array avec fetch_array
while ($row = $result->fetch_array())
{
// 3.b. création du nouvel array pour affichage hors de la boucle
$villes[$row['ville_id']] = $row['ville_nom'];
}
// 4. Affichage
?>
</div>
<ul>
<li><a href="index.php">Accueil</a></li>
<?php foreach($villes as $id => $ville) : ?>
<li><a href="ville.php?id=<?php echo $id ?>"><?php echo $ville ?></a></li>
<?php endforeach ?>
</ul>
<?php
/* Libération des résultats */
$result->free();
/* Fermeture de la connexion */
$mysqli->close();
?>
</body>
</html>


Il faut surement faire des modifications pour que une seule ville s'affiche et pas toutes . Mais je ne sais pas vraiment comment faire . Je continue à chercher .
Modérateur
Si elles s'affichent toutes c'est parce que la génération du lien est contenue dans une boucle. Si vous virez la boucle mais ne gardez que le lien, vous obtiendrez un lien unique associé à $id récupéré en GET.


Toutefois, ne serait-il pas plus intéressant de charger directement la page plutôt que d'en afficher le lien ? Je dis ça je ne dis rien Smiley cligne


Autre-chose aussi qui me saute aux yeux, il vaut mieux bien séparer vos différents langages. Certes parfpois on ne peut faire autrement comme dans le cas de l'utilisation d'une variable php au sein du html. Mais pour le reste, le traitement à proprement parler il vaut mieux, dans un soucis de lisibilité et de maintenabilité les séparer.

En reprenant votre script, je vous suggère de plutôt partir ainsi
<?php
  // 1. récupération de la variable externe
  $id =(int) $_GET['id'];
  // 2. connexion à la base
  $mysqli = new mysqli('localhost', 'root', '', 'projet_villes');
  // 3. requête.
  // Concaténation de la requete avec la variable $id.
  $result = $mysqli->query('SELECT ville_id, ville_nom, ville_texte FROM
  villes WHERE ville_id = ' . $id );
  // 4. création du nouvel array
  $row = $result->fetch_array();
  // 5. Affichage
  $nom   = $row['ville_nom'];
  $texte = $row['ville_texte'];
  // 2. requête
  $result = $mysqli->query('SELECT ville_id, ville_nom FROM villes');
  // 3.a. transformation en array avec fetch_array
  while ($row = $result->fetch_array())
  {
    // 3.b. création du nouvel array pour affichage hors de la boucle
    $villes[$row['ville_id']] = $row['ville_nom'];
  }
?>
<!DOCTYPE html>
  <html>
    <head>
      <title><?php echo $nom ?></title>
      <link rel="stylesheet" type="text/css" href="style.css" />
    </head>
    <body>
      <div>
        <h1><?php echo $nom ?></h1>
        <p><?php echo $texte ?></p>
      </div>
      <?php // 4. Affichage ?>
      <ul>
        <li><a href="index.php">Accueil</a></li>
        <?php foreach($villes as $id => $ville) : ?>
          <li><a href="ville.php?id=<?php echo $id, $ville ?></a></li>
        <?php endforeach ?>
      </ul>
    </body>
  </html>
<?php
/* Libération des résultats */
$result->free();
/* Fermeture de la connexion */
$mysqli->close();
?>



Tant que j'y suis dans les conseils avisé:
* Indentez votre code, vous verrez qu'à terme ce n'est pas du temps perdu.
* le saviez-vous ?
<?php echo $variable;?>
<!-- peut s'écrire -->
<?= $variable;?>

<!-- l'élément '<?=' signifie '<?php echo' -->


* l'écriture ternaire coûte plus cher que l'écriture procédurale.


Autre-chose, vous êtes-vous demandé ce qu'il se passait lorsque l'utilisateur modifie la valeur de l'id dans son url et utilise une valeur inconnue en base de donnée comme 999999999 ? (à méditer).


C'est tout.... pour le moment ! Smiley cligne
Smiley smile Smiley biggrin
Modifié par Greg_Lumiere (17 Apr 2018 - 09:38)
Bonjour, vous avez raison il est vrai que de séparer les différents langages permet d'avoir une meilleure lisibilité je vais appliquer vôtre conseil dans mes prochaines création. Et je ne savais pas du tout que l'on pouvait écrire de cette manière . Encore quelque chose que je viens d'apprendre .

Par rapport au code si c'est bien cela qu'il fallait faire j'ai supprimer la boucle foreach où il y avait le lien de la page et je n'ai gardé que celle-ci. Mais lors de la saisie d'une ville j'ai mon lien Accueil qui s'affiche bien et en dessous il devrait y avoir la ville mais je n'ai qu'un simple point du au html <li> et de plus j'ai toujours au dessus ce message d'erreur : Undefined index: id in qui correspond à ça : $id =(int) $_GET['id']; .
Modérateur
[code=php]$id =(int) $_GET['id'];[/php]
Si je décris littéralement ceci j'obtiens
Définition de la variable 'id' qui est égale au cast de la valeur obtenue dans la table locale GET.
1. Pourquoi faire un cast de la valeur (cast = forcer le type d'une valeur) ; ceci est rarement utilisé. Perso je préfère travailler avec le type natif des éléments récupérés. Ici vous obtenez un string (et non un integer [un nombre]) mais en quoi cela peut-être gênant ?

2. Êtes-vous sûr que $_GET['id'] existe ? En tête de page vous pourriez tester le contenu de $_GET afin déjà d'être sûr que cette valeur est bien transmise.
Pour ce faire un simple print_r($_GET) vous affichera tout le tableau
PS : vérifiez que dans votre formulaire la méthode utilisée est bien GET. Si c'est post... Vous me suivez ?
Edit : A relire je m'aperçois qu'il semble que ce point soit correct mais je laisse au cas où.
Edit n°2 : Pourtant en tête de ce sujet votre formulaire décrit une méthode "post"... Vous avez changé ?

3. Dans votre html vous utilisez en référence $ville mais vous avez défini où cette variable ? Si j'ai bien suivis le truc (pas sûr) vous devriez plutôt avoir un truc du genre $villes[$id] où villes correspond au tableau récupéré dans votre bdd et qui devrait ressembler à ceci:
[0] => Paris,
[1] => Montpellier,
[2] => Calais
etc...

4. Parfois ça m'arrive et si vous aussi vous n'y voyez pas le jour, tentez donc de reprendre votre projet de page depuis une feuille vierge. En général quand je fais ça j'obtiens un bien meilleur résultat, plus concis et plus efficient. Dans votre cas j'ai l'impression que vous vous emmêlez les pinceaux.
Modifié par Greg_Lumiere (17 Apr 2018 - 13:26)
En effet je suis même perdue , j'ai une bonne compétence en html et css mais en ce qui concerne php je débute et j'ai du mal.

J'ai ajouté print_r($_GET) au début et j'ai ce message d'erreur qui s'affiche syntax error, unexpected '$id' (T_VARIABLE) donc j'ai une erreur d'analyse syntaxique : erreur de syntaxe, fin de code inattendue » . Autrement dit, quelque chose ne se termine pas correctement dans mon code.
Greg_Lumiere a écrit :
[code=php]$id =(int) $_GET['id'];[/php]
Si je décris littéralement ceci j'obtiens
Définition de la variable 'id' qui est égale au cast de la valeur obtenue dans la table locale GET.
1. Pourquoi faire un cast de la valeur (cast = forcer le type d'une valeur) ; ceci est rarement utilisé. Perso je préfère travailler avec le type natif des éléments récupérés. Ici vous obtenez un string (et non un integer [un nombre]) mais en quoi cela peut-être gênant ?


En l’état ça permet, de manière détournée, que rien de problématique sera introduit dans sa requête SQL..
Modérateur
Adwim a écrit :

En l’état ça permet, de manière détournée, que rien de problématique sera introduit dans sa requête SQL..
De manière détournée, exactement !
Le soucis est que si un élément "problématique" est inséré via l'url, $id sera alors systématiquement égal à zéro or zéro correspond probablement à une ville dans la table alors qu'une vérification en bonne et due forme permettra de signaler au visiteur que l'élément choisit pose problème et pouvoir lui en donner la cause et/ou le rediriger vers le sélecteur.

Le tout c'est d'en avoir conscience. Smiley cligne
Donc est ce que je dois utiliser cet exemple de variables ? :
String phrase;
phrase = "Titi et Grosminet";
Modérateur
Bonjour Artotec,

Je ne comprends pas fort bien ce que votre exemple vient faire dans l'histoire.

Afin d'être sûr que nous parlions le même langage, reprenons les bases.

Il existe divers types de variables, c'est vrai en PHP mais aussi dans d'autres langages:
- les booléens : true/false (traduits parfois par 0/1)
- les integer : nombres entiers
- les float : nombres à virgule
- les string : chaînes de caractère
- les array : tableaux
etc

Les données transmises par un formulaire ne peuvent l'être que via 2 méthodes:
- POST : transmission via les cookies ; invisible aux yeux de l'utilisateur (sauf s'il fouille dans son navigateur)
- GET : transmission via l'url (directement sous les yeux de l'utilisateur).
Quelque soit la méthode utilisée, le formulaire envoi toujours des données de type string (ou un tableau contenant lui même des valeurs de type string ; cas des checkbox et boutons radio).


Du côté de la réception des données, de quels éléments devons-nous tenir compte ?
D'abord de la méthode de transmission des données. Ainsi pour la méthode POST on fera nos checks sur la variable globale $_POST et bien évidemment on s'adressera à $_GET pour les autres.
Par contre, quelque soit notre volonté, on obtient des données de type string (important !).

La première chose à faire est de vérifier de l'existence de la données attendue ; dans le sujet qui nous occupe on vérifiera donc que $_GET['id'] existe.
La deuxième sera de sécuriser cette donnée au cas où "un petit malin" tentera une injection indésirable ou tout simplement au cas où la donnée serait corrompue (intentionnellement ou non). Pour ce faire Php embarque plusieurs fonctions de vérification comme par exemple htmlentities() (pour en savoir plus, rdv sur php.net).
Enfin nous utiliserons des opérateurs de comparaison (supérieur, égale, inférieur etc)afin d'être sûr que la données attendue corresponde à nos attentes.

A noter que dans l'exemple qui suit, les deux lignes reviennent au même:
if ("42" > 10) { echo "YEAH !"; }
/* Si 42 de type string est supérieur à 10, afficher le texte */

if (42 > 10 { echo "YEAH !"; }
/* Si 42 de type entier est supérieur à 10, afficher le texte */


/*
===> Ces deux lignes renverront toutes deux le texte "YEAH !"
*/



Voici pour la théorie.


En pratique, voici ce que succinctement cela peut donner en reprenant notre cas sur l'id transmise par l'url:
  /* On déclare la variable dont on aura besoin */
  $id = '';
  /* On vérifie de l'existence de la donnée transmise et on la sécurise */
  if (!empty($_GET['id'])) { $id = htmlentities($_GET['id']); }
  /* On vérifie que $id est bien hydratée sinon on redirige le visiteur */
  if (empty($id)) { header('locate: page_de_selection.php'); }
  
  /* Maintenant on peut travailler avec la variable $id ET
     on n'utilise plus jamais $_GET['id'] ! */
     
  /* Enfin, une fois la connexion vers la base de donnée établie,
     on s'assurera que $id existe dans la table avant de poursuivre l'affichage et le traitement */



Voilà à peu de choses près comment je procède et je me suis aperçu que beaucoup faisaient pareil ; il doit bien il y avoir une raison, non ? Smiley cligne


A parte: bien évidement je ne remets en cause le fait de faire un cast de la valeur et si vous êtes plus à l'aise ainsi, pourquoi pas. Néanmoins je trouve que cette méthode n'est pas exempt de défaut alors que de la façon que je vous ai décris, le développeur à un meilleur contrôle sur la donnée reçue et son traitement. Et puis je dois l'avouer, je préfère (n'est-ce pas suffisant comme motif ? Smiley biggrin )

Note: Il va de soit que pour l'exemple je m'en suis tenu à une version des plus simplistes et que nombre de vérification, fonctions de la situation, peuvent-être implémentées afin de rendre le code plus robuste et le traitement plus sûr.


2nd note: Les chrétiens ont la Bible, les musulmans le Coran, Fidel Castro les cigares [...] nous, nous avons PHP.NET Smiley biggrin


Maintenant que nous avons bien revus les bases et que nous nous sommes bien perdus en tergiversation, il serait temps de refaire un point sur la situation. Précisez à nouveau votre problème et re-postez votre code dans son état actuel (en tenant compte tout de même de mes remarques Smiley cligne ). A nous tous on devrait bien arriver à résoudre votre chmilblik Smiley smile
Modifié par Greg_Lumiere (18 Apr 2018 - 08:51)
Modérateur
Un point que je n'ai pas évoqué et qui pourtant à une importance capitale (même si j'en vois beaucoup ici-bas qui n'en tiennent pas compte):

NE JAMAIS SE FIER AUX DONNÉES PROVENANT DE L’EXTÉRIEUR DU SERVEUR !

On voit souvent ceci rabâché mais ça ne dit pas concrètement ce qu'il faut en faire.

Toute donnée provenant de l'extérieur du serveur est à considérer comme une menace avérée.
Oui j'ai bien dis <span style="font-size: enormous; font-weight: extra-bold; text-decoration: underline_x4; color: red_pettant; text-effect: clignotant;"> avérée </span>.
C'est à dire qu'il faille imaginer le cas où vous tombez sur le pire truand de la Galaxie des Ours qui va vous injecter les plus grosses infamies.

C'est pourquoi, en premier lieu, il faut toujours sécuriser ses données. Php embarque des fonctions natives très efficaces qui, mises bout-à-bout, assurent d'obtenir des données saines.

Donc en tête de script, toujours:
1, vérifier que la donnée existe
2, nettoyer la donnée reçue et assigner une donnée assainie à une variable
3, utilisation de la variable saine et plus jamais de la donnée reçue.
0, prévoir un fallback au cas où 1, 2 et 3 se sont pas remplis !
Modifié par Greg_Lumiere (18 Apr 2018 - 09:06)
Merci pour vos tous vos conseils je vais m'occuper de ce problème grâce à vos précieux informations et vous tiendrez au courent . Smiley biggrin
Je n'ai plus de soucis avec $GET['id'] mais j'ai un problème avec $row = $result->fetch_array(); j'ai ce message d'erreur qui s'affiche :
Fatal error: Call to a member function fetch_array() on boolean

Je pense que cette erreur provient du fait de la syntaxe de la Syntaxe SQL, envoyer à la Base de Données, erreur sur le nommage des tables, des champs, des espaces

 $result = $mysqli->query('SELECT ville_id, ville_nom, ville_texte FROM
  villes WHERE ville_id = ' . $id );


Qu'en pensez-vous ?
Modérateur
artotec a écrit :
erreur sur le nommage des tables, des champs
Oui je pense que le soucis vient de là.


PS: je ne suis pas un spécialiste de la bdd car le besoin ne s'en faisant pas expressément sentir je n'ai fait que survoler le chapitre PDO. Ça n'a pas l'air bien sorcier alors quand j'aurais suffisamment de données à traiter pour justifier l'usage d'une base de donnée, il sera encore temps de m'y mettre Smiley biggrin
Du peu que j'en ai lus, PDO avec ses requête préparées c'est le top du top ! Smiley cligne
Mais du coup, ta requête
SELECT ville_id, ville_nom, ville_texte FROM
villes WHERE ville_id = // l'id que tu es sensé recevoir dans ton get

en base elle donne quoi ?