Moteur de recherche PHP & MySQL

Problème d'affichage de résultats

Le problème exposé dans ce sujet a été résolu.

Bonsoir tout le monde. C’est mon premier topic sur le forum, donc soyez indulgents si je fais des erreurs svp ^^. J’ai commencé à créer un moteur de recherche basique en PHP et MySQL, sauf que mes résultats ne s’affichent pas: ma page s’affiche sans erreurs, mais lorsque j’entre un auteur dans mon champ de recherche, et que j’exécute ma requête, il ne trouve aucun résultat, alors qu’il devrait en avoir au moins 1.

Le but est d’effectuer une recherche bibliographique dans une base de données nommée ’bibli’. J’aimerais donc qu’en cherchant un auteur dans la table ’authors’ de cette BDD, on puisse tomber sur le nombre de livres écrit par cet auteur, ainsi que leur titre, dont les références sont stockées dans la table ’notices’.

Voilà le schéma de ma BDD (c’est fait à la va-vite avec Paint hein, c’est pas du grand art ^^):

Schéma de la base de données ’Bibli’

Voilà mon code pour que vous puissiez tester par vous-mêmes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Moteur de recherche</title>
  </head>
  <body>
    <form action=<?php echo $_SERVER['PHP_SELF']; ?> method="post">
      <label for="search">Entrez votre recherche: </label>
      <input type="search" name="search" value="">
      <input type="submit" name="submit" value="valider">
    </form>
  </body>
</html>

<?php

//Initialisation de la variable $resultats
$resultats = "";

//traitement de la requête
if (isset($_POST['search']) && !empty ($_POST['search'])) {
//on vérifie si l'utilisateur a entré des termes à rechercher, et on traite sa requête

//connexion à la base de données
try {
  $db = new PDO('mysql:host=localhost;dbname=bibli', 'root','');
} catch (PDOException $e) {
  die($e.getMessage());
}

$query = preg_replace("#[^a-zA-Z ? 0-9]#i", "", $_POST['search']);

//Requête de sélection MySQL
$req = $db->prepare("(SELECT * FROM authors WHERE author_name AS nom LIKE ?) UNION
  (SELECT * FROM notices WHERE tit1 AS titre LIKE ?)");

$req->execute(array('%' . $query . '%', '%' . $query . '%'));

//On compte les résultats
$count = $req->rowCount();

//On traite les résultats
if ($count >= 1) {
  echo "$count résultats trouvés pour <strong> '$query' </strong> \n '$req'";

  while ($data = $req->fetch(PDO::FETCH_OBJ)) {
    echo "Auteur :" . $data->nom . ", titre : " . $data->titre;
  }
} else {
  echo "\n <hr /> Aucun résultat trouvé pour <strong> '$query' </strong> \n";
}

}
?>

  <?php echo "\n" . $resultats ?>

Je tiens à préciser que ce code a été adapté de celui d’une vidéo Youtube (Les teachers du Net, "Créer un moteur de recherche en PHP pour votre site"), et que je suis plutôt débutant en PHP (j’ai suivi le cours dédié à PHP/MySQL d’Openclassrooms avant de découvrir ce site prometteur :) ).

D’avance merci pour votre aide!

+0 -0

Bonjour,

Tout d’abord, tu dis que le code ne fonctionne pas. Comment ça ? Il ne renvoie pas les résultats attendus, ou il cause une erreur ? Et laquelle ?

Ensuite, pour pouvoir analyser ton code, il nous manque la structure de la base de données. Sans elle, il nous est impossible de visualiser la façon dont PHP communique avec MySQL (ou un autre SGBDR, libre à toi d’utiliser celui que tu préfères).

Par ailleurs, il est fortement déconseillé de mettre du code HTML avant le PHP. En effet, cela cause des problèmes lors de l’utilisation de cookies, puisque ceux-ci doivent être envoyés avant toutes autres données. De plus, il est plus compliqué d’avoir une structure correctement construite, au niveau HTML.

Par exemple, ton code peux donner la structure suivante en sortie de PHP :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Moteur de recherche</title>
  </head>
  <body>
    <!-- Ici, la valeur de `action` peut être incohérente pour le navigateur. Il vaut mieux ne pas mettre ce champ, puisque la validation du formulaire est faite à la même adresse que son émission -->
    <form action=localhost/blabla/foo/bar.php method="post">
      <label for="search">Entrez votre recherche: </label>
      <input type="search" name="search" value="">
      <input type="submit" name="submit" value="valider">
    </form>
  </body>
</html>

8 résultats trouvés pour <strong> 'truc' </strong>
'bidule'
Auteur :Dickens, titre : Un bouquinAuteur :Dickens, titre : Un bouquinAuteur :Dickens, titre : Un bouquinAuteur :Dickens, titre : Un bouquinAuteur :Dickens, titre : Un bouquin
Quelques resultats

Tu remarqueras que tout ce que sort PHP via la fonction echo est mis à la suite. Et en plus, hors d’un quelconque tag HTML, ce qui complique la tache du navigateur et ne donne pas de résultat fiable.

+1 -0

Salut !

Tu as une page blanche ? Si oui, une des premières choses à faire en cas de symptôme de la page blanche, c’est d’activer l’affichage des messages d’erreur de PHP ET de PDO. Ce faisant, tu auras l’indication que ta requête n’est pas valide au niveau syntaxe : on ne peut pas mettre un alias sur un nom de colonne dans la clause WHERE, ça doit se passer dans la clause SELECT.

Ensuite, je ne pense pas que ce que tu souhaites faire soit une union, mais plutôt une jointure, ce qui n’est pas la même chose. Je te conseille de reprendre un tutoriel sur le SQL, peut-être celui sur MySQL présent sur ce site. Sans information sur la structure de tes tables, on ne pourra pas vraiment faire mieux que de la théorie.

+0 -0

Bonsoir à vous!

Merci pour vos réponses rapides. J’ai mis à jour mon post initial pour répondre à vos questions. Je n’ai pas listé tous les champs, car je travaille sur le logiciel PMB (c’est un système de gestion de bibliothèques open source), qui créé énormément de champs et de tables. S’il vous faut tous les champs, le plus simple serait de pouvoir vous envoyer le schéma de la table au format SQL.

J’ai également modifié l’emplacement de mon formulaire pour qu’il vienne après le code PHP.

J’ai activé les erreurs PHP et PDO, et effet, il s’agit d’une erreur de syntaxe SQL. Je me suis donc lancé dans une jointure interne en lisant le tuto, mais je ne trouve pas de correspondance d’ID entre les notices et les auteurs… Je vous tient au courant le plus vite possible.

Merci de votre aide! Bonne soirée!

+0 -0

je travaille sur le logiciel PMB

Il ne dispose pas déjà d’un système de recherche ? Le CDI de mon Collège/Lycée l’utilise et il y en avait un…

J’ai également modifié l’emplacement de mon formulaire pour qu’il vienne après le code PHP.

Montre nous comment tu as fait, s’il te plait.

J’ai activé les erreurs PHP et PDO, et effet, il s’agit d’une erreur de syntaxe SQL.

Quel est le message d’erreur que tu obtiens ? Ça nous permettrait de t’aider plus efficacement.

+0 -0

L’erreur doit plus ou moins dire "Syntax error near WHERE author_name AS nom".  ^^

Ce faisant, tu auras l’indication que ta requête n’est pas valide au niveau syntaxe : on ne peut pas mettre un alias sur un nom de colonne dans la clause WHERE, ça doit se passer dans la clause SELECT.

Ymox
+0 -0

Bonsoir,

Voilà le message d’erreur que me renvoie PHP (excusez-moi, la capture d’écran est un peu petite…): Erreur de syntaxe SQL

Il s’agit donc bel et bien d’une erreur concernant mon alias Ymox. Je vais essayer de résoudre l’erreur prochainement grâce à une jointure interne (merci pour le tuto, Amael ;) ).

Pour le reste, PMB propose en effet un système de recherche, mais au niveau de l’OPAC, on ne peut pas faire une recherche directe par titre, auteur ou mots-clés. Il faut passer par la recherche avancée, puis ajouter des champs… Ce qui n’est pas très intuitif (je suis étudiant bibliothécaire et l’institution dans laquelle je suis en stage aimerait que ça évolue vers un système plus pratique, d’où ce premier essai). Le développement web ne fait pas partie de mes tâches, mais j’aime bidouiller… :D .

Voilà donc ma feuille de code actualisée, pour répondre à ta 2ème question, Amael:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php

//Initialisation de la variable $resultats
$resultats = "";

//traitement de la requête
if (isset($_POST['search']) && !empty ($_POST['search'])) {
//on vérifie si l'utilisateur a entré des termes à rechercher, et on traite sa requête

//connexion à la base de données
try {
  $db = new PDO('mysql:host=localhost;dbname=bibli', 'root','', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch (PDOException $e) {
  die($e.getMessage());
}

$query = preg_replace("#[^a-zA-Z ? 0-9]#i", "", $_POST['search']);

//Requête de sélection MySQL
$req = $db->prepare("SELECT author_name, tit1 FROM authors, notices INNER JOIN notices ON author_id = /*nom du champ clé étrangère des auteurs pour faire la jointure correctement*/ WHERE author_name LIKE ?");

$req->execute(array('%' . $query . '%'));

//On compte les résultats
$count = $req->rowCount();

//On traite les résultats
if ($count >= 1) {
  echo "$count résultats trouvés pour <strong> '$query' </strong>";

  while ($data = $req->fetch(PDO::FETCH_OBJ)) {
    echo "Auteur :" . $data->author_name . ", titre : " . $data->tit1;
  }
} else {
  echo "\n <hr /> Aucun résultat trouvé pour <strong> '$query' </strong>";
}

}
?>

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Moteur de recherche</title>
  </head>
  <body>
    <form action=<?php echo $_SERVER['PHP_SELF']; ?> method="post">
      <label for="search">Entrez votre recherche: </label>
      <input type="search" name="search" value="">
      <input type="submit" name="submit" value="valider">
    </form>
  </body>
</html>

  <?php echo "\n" . $resultats ?>

Malheureusement, ce code produit cette erreur-ci, que je ne comprends pas trop:

Erreur 1066 : table/alias multiple

Actuellement, j’ai donc 3 problèmes à régler:

  1. Trouver la cause de cette erreur 1066.
  2. Trouver le champ commun entre les notices et les auteurs pour faire une jointure.
  3. Avoir une syntaxe correcte pour ma jointure (je suivrai donc le tuto à la lettre ;) ).

Voilà, j’espère avoir été complet. Je vous tient au courant ce WE si jamais j’ai progressé. Merci encore pour votre aide! Bonne fin de soirée!

Mx47

+0 -0

Bonsoir, ou bonjour, en fonction du moment où tu liras ce message,

Par rapport au code, j’ai trois remarques à faire :

Premièrement, quel est l’objectif de la ligne 17 ?

Si c’est l’échappement des éventuelles injections SQL, c’est raté, cf l’article d’Ymox sur la question.

Sinon, sache que $query == "" est toujours vrai après cette ligne à cause de la valeur renvoyée par preg_replace.

Deuxièmement, à la ligne 48, il faut retirer l’attribut action de la balise form, il ne sert à rien dans le cas présent. Ou alors tu met le code PHP de cette ligne entre guillemets afin de définir proprement l’attribut.

Enfin, tu as effectivement déplacé le traitement PHP, mais celui-ci réalise toujours des echo qui cassent l’arbre HTML, et qui peuvent casser la reconnaissance de ce dernier par le navigateur.

Au lieu de faire

1
echo $foo;

Fait plutôt

1
$resultats += $foo;

Puis, dans la zone d’affichage (dans le HTML) tu mettra

1
<?php echo $resultats ?>

Mais tu ne dois pas faire d’echo en dehors des balises <html> ... </html>.

Amael

+0 -0

Salut Amael,

Merci pour tes conseils. Excuse-moi pour le retard de ma réponse, mais j’ai été fort pris pour l’école. D’abord, pour la question des fonctions echo, j’ai essayé d’appliquer ton conseil, mais du coup, quand je veux afficher des résultats, je n’ai plus que leur nombre, et plus de texte (sans aucune erreur de syntaxe ou autre). Aurais-tu une idée?

Sinon, pur la ligne 17, je n’ai qu’une bête réponse: j’ai suivi le tuto sans me poser de questions (ce qui est un peu con). Mais, je suppose qu’en effet, c’est pour éviter l’injection SQL. Je lirai à ce propos l’article d’Ymox prochainement.

Voilà mon code actuel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php

//Initialisation de la variable $resultats
$resultats = "";

//traitement de la requête
if (isset($_POST['search']) && !empty ($_POST['search'])) {
//on vérifie si l'utilisateur a entré des termes à rechercher, et on traite sa requête

//connexion à la base de données
try {
  $db = new PDO('mysql:host=localhost;dbname=bibli', 'root','', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch (PDOException $e) {
  die ($e->getMessage());
}

$query = $_POST['search'];

//Requête de sélection MySQL
$req = $db->prepare("SELECT author_name FROM authors INNER JOIN notices ON author_id = notice_id WHERE author_name LIKE ?");

/*$req->execute(array('%' . $query . '%'));*/

//On compte les résultats
$count = $req->rowCount();

//On traite les résultats
if ($count >= 1) {
  $resultats += "$count résultats trouvés pour <strong> '$query' </strong>";

  while ($data = $req->fetch(PDO::FETCH_OBJ)) {
    $resultats += "Auteur :" . $data->author_name . ", titre : " . $data->tit1;
  }
} else {
  $resultats += "\n <hr /> Aucun résultat trouvé pour <strong> '$query' </strong>";
}

}
?>

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Moteur de recherche</title>
  </head>
  <body>
    <form method="post">
      <label for="search">Entrez votre recherche: </label>
      <input type="search" name="search" value="">
      <input type="submit" name="submit" value="valider">
    </form>

    <?php echo "\n" . $resultats ?>

  </body>
</html>

`

J’ai placé la requête execute (ligne 22), entre parenthèses, car je ne savais pas quoi en faire… Je ne sais pas comment la structurer… :(

Merci d’avance pour ton aide, bye! :D

Merci pour tes conseils. Excuse-moi pour le retard de ma réponse, mais j’ai été fort pris pour l’école. D’abord, pour la question des fonctions echo, j’ai essayé d’appliquer ton conseil, mais du coup, quand je veux afficher des résultats, je n’ai plus que leur nombre, et plus de texte (sans aucune erreur de syntaxe ou autre). Aurais-tu une idée?

Excuse moi, j’avais oublié la syntaxe de la concaténation en PHP :honte:
Utilise .= au lieu de +=.

Sinon, pur la ligne 17, je n’ai qu’une bête réponse: j’ai suivi le tuto sans me poser de questions (ce qui est un peu con). Mais, je suppose qu’en effet, c’est pour éviter l’injection SQL. Je lirai à ce propos l’article d’Ymox prochainement.

Si le tuto est bon, ça devrait être bon, mais lis quand même l’article, il est très intéressant.

+0 -0

Salut Amael,

Merci pour ton aide, ça fonctionne désormais très bien! :D

Voilà mon code final si ça te dit :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php

//Initialisation de la variable $resultats
$resultats = "";

//traitement de la requête
if (isset($_POST['search']) && !empty ($_POST['search'])) {
//on vérifie si l'utilisateur a entré des termes à rechercher, et on traite sa requête

//connexion à la base de données
try {
  $db = new PDO('mysql:host=localhost;dbname=bibli', 'root','', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch (PDOException $e) {
  die ($e->getMessage());
}

$query = $_POST['search'];

//Requête de sélection MySQL
$req = $db->prepare("SELECT * FROM authors a INNER JOIN notices n ON author_id = notice_id WHERE author_name LIKE ?");

$req->execute(array('%' . $query . '%'));

//On compte les résultats
$count = $req->rowCount();

//On traite les résultats
if ($count >= 1) {
  $resultats .= "$count résultats trouvés pour <strong> '$query' </strong> <br />";

  while ($data = $req->fetch(PDO::FETCH_OBJ)) {
    $resultats .= "<br /> Auteur :" . $data->author_name . ", " . $data->author_rejete . ". Titre : " . $data->tit1;
  }
} else {
  $resultats .= "\n <hr /> Aucun résultat trouvé pour <strong> '$query' </strong>";
}

}
?>

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Moteur de recherche</title>
  </head>
  <body>
    <form method="post">
      <label for="search">Entrez votre recherche: </label>
      <input type="search" name="search" value="">
      <input type="submit" name="submit" value="valider">
    </form>

    <?php echo "\n" . $resultats ?>

  </body>
</html>

`

Salut,

Content de voir que tu as réussi.

Cependant, il y a un petit détail de HTML que l’on n’a pas bien vu. C’est le tag <html lang="en" dir="ltr"> qui devrait être <html lang="fr" dir="ltr"> pour simplifier le travail des traducteurs de site (et des lecteurs d’écran, ces logiciels utilisés par les malvoyants).

À part ce détail, c’est tout bon.

Amael

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte