8797 sujets

Développement web côté serveur, CMS

Bonjour à tous !

J'ai une table "articles", qui comporte trois champs "article_id", "article_titre" et "article_liens".

Je souhaite que lorsque je suis sur une page article, à droite s'affiche les autres articles liés, situés dans "articles_liens" sous la forme "1,3, etc." (énumération séparée par une virgule, qui correspondent aux id des articles liés).

Voici le code que j'ai tenté :


$reperearticle = $_GET['article'];
$requete = mysql_query("SELECT * FROM articles WHERE article_id LIKE'".$reperearticle."'");
			  	  		
while ($donnees = mysql_fetch_array($requete))
{
    echo "<h3 class='lireaussi'>lire aussi sur ce site</h3>" ;
    echo "<p class='lireaussitexte'>Pour compl&egrave;ter la lecture de cet article, vous pouvez lire &eacute;galement sur ce site :</p>" ;
    echo "<ul class='lireaussicontent'>" ;
				
    /* je recupere le champ "article_liens" de ma table */					
    $article_liens = $donnees['article_liens']; 		
    /* je stocke chaque réponse dans un tableau en les scindant à la virgule*/							
    $tableau_liens = explode(",", $article_liens);
    
    /* la taille du tableau peut servir pour une boucle ? */
    $tailledutableau= sizeof($tableau_liens);
						
    /* je souhaite récupérer le titre de chaque article renseigné par $article_liens */			
    $article_titre = $donnees['article_titre']; 
    $article_titre = stripslashes(htmlspecialchars($article_titre, ENT_QUOTES, 'UTF-8', $double_encode));	
										
       /* je veux que pour chaque entrée du tableau qui existe, on restitue un lien dans un li */
	foreach ($tableau_liens as $identifiant)
	 {										
	  echo "<li><a href='index.php?section=&article=".$identifiant."' title='Consulter cet article : ".$donnees['article_titre']."'>".$donnees['article_titre']."</a></li>";
	}
	
										
	echo "</ul>" ;
									
	}


Ici $donnees['article_titre'] restitue toujours le titre de l'article affiché, et non pas ceux des articles liés...

Je n'arrive pas à savoir comment changer cette variable, ou comment écrire la requête : soit je perd l'id d'article lié, soit je perd son titre...

Help !
Modifié par montoumes (16 Jul 2008 - 13:42)
Hello,

alors déjà ta table n'est pas normalisée (et l'un des signes pour le savoir est qu'une requête devient très compliquée à faire Smiley langue ) : le champ articles_liens qui contient plusieurs valeurs séparées par une virgule cémal ! (voir à ce sujet un thread récent).

Pour "bien faire" je verrais plutôt 2 tables :
articles
- article_id
- article_titre

liens_articles
- article_id_base
- article_id_lie

Ensuite il ne reste plus qu'à faire 2 boucles : la première est celle que tu exécutes déjà, et à l'intérieur une autre pour récupérer tous les articles liés.
Modifié par Heyoan (12 Jul 2008 - 12:49)
Donc si je résume, il me faut un

Un premier while qui interroge "articles" pour générer mes <ul> en fonction de l'article ($_GET['article'])

et dedans un second while qui interroge "liens-articles".

Mais comment dois-je écrire la seconde boucle ? quel est le principe qui relie "articles" et "liens-articles" ? (je ne demande pas le code, mais l'idée maîtresse de cette boucle)

Merci !
montoumes a écrit :
Mais comment dois-je écrire la seconde boucle ? quel est le principe qui relie "articles" et "liens-articles" ? (je ne demande pas le code, mais l'idée maîtresse de cette boucle)
Euh... en fait ça va être plus simple pour moi de mettre le code que de le dire en français Smiley lol :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<title>Test</title>
	<style type="text/css" media="screen,projection"><!--
		/* Contenu du bloc CSS */

	--></style>
</head>
<body>
<?php
require_once('tests/connexion.php');
$reperearticle = !empty($_GET['article']) ? intval($_GET['article']) : 0;
if ( $reperearticle > 0 ) { // Si un code article est renseigné dans l'url
	$sql1 = "Select article_titre from articles where article_id = $reperearticle";
	$result1 = mysql_query($sql1) or die(mysql_error());
	if ( mysql_num_rows($result1) > 0 ) { // Si ce code article existe dans la base
		$row1 = mysql_fetch_assoc($result1);
		echo "<p>l'article n° <strong>".$reperearticle."</strong> (".$row1['article_titre'].") est composé de :</p>\n";
		echo "<ul>\n";
		$sql2 = "Select article_id, article_titre from articles, liens_articles where article_id_base = $reperearticle and article_id_lie = article_id";
		$result2 = mysql_query($sql2) or die(mysql_error());
		if ( mysql_num_rows($result2) > 0 ) { // Si un (ou des) code(s) article sont associé(s) au 1er article
			while ($row2 = mysql_fetch_assoc($result2)) {
				echo "\t<li><a href='index.php?section=&article=".$row2['article_id']."' title='Consulter cet article : ".$row2['article_titre']."'>".$row2['article_titre']."</a></li>\n";
			}
		echo "</ul>\n";
		}
	}
}
?>
</body>
</html>

test effectué avec les 2 tables suivantes :
-- phpMyAdmin SQL Dump
-- version 2.10.1
--  http://www.phpmyadmin.net
 
-- 
-- Serveur: localhost
-- Généré le : Sam 12 Juillet 2008 à 12:50
-- Version du serveur: 5.0.41
-- Version de PHP: 5.2.3

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

-- 
-- Base de données: 'test'
-- 

-- --------------------------------------------------------

-- 
-- Structure de la table 'articles'
-- 

CREATE TABLE articles (
  article_id tinyint(4) NOT NULL auto_increment,
  article_titre varchar(30) NOT NULL,
  UNIQUE KEY article_id (article_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 
-- Contenu de la table 'articles'
-- 

INSERT INTO articles VALUES (1, 'marteau');
INSERT INTO articles VALUES (2, 'boulon');
INSERT INTO articles VALUES (3, 'écrou');
INSERT INTO articles VALUES (4, 'pioche');

-- --------------------------------------------------------

-- 
-- Structure de la table 'liens_articles'
-- 

CREATE TABLE liens_articles (
  article_id_base tinyint(4) NOT NULL,
  article_id_lie tinyint(4) NOT NULL,
  KEY article_id (article_id_base)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 
-- Contenu de la table 'liens_articles'
-- 

INSERT INTO liens_articles VALUES (1, 2);
INSERT INTO liens_articles VALUES (1, 3);
INSERT INTO liens_articles VALUES (1, 4);

A+
Une question me taraude.... Smiley smile

Dans le cas de figure que j'ai choisit, est-ce que ta méthode n'oblige pas à dupliquer l'enregistrement dans "liens_article" si je veux que celui-ci soit lié à deux articles ?

En tout cas si on a que trois champs, ce n'est pas bien grave me semble-t-il ? Smiley smile

Merci en tout cas pour ton aide !
Modifié par montoumes (14 Jul 2008 - 19:32)
montoumes a écrit :
Dans le cas de figure que j'ai choisit, est-ce que ta méthode n'oblige pas à dupliquer l'enregistrement dans "liens_article" si je veux que celui-ci soit lié à deux articles ?
Euh... pas compris Smiley rolleyes ! Si un article est un "composant" de plusieurs articles son identifiant sera effectivement présent dans plusieurs enregistrements de la tables "liens". Cela ne pose aucun problème et est normalisé.

montoumes a écrit :
En tout cas si on a que trois champs, ce n'est pas bien grave me semble-t-il ? Smiley smile
Je ne peux que te conseiller de normaliser tes tables mais tu es libre. J'aime bien cette réponse de Lanza à ce sujet.
Ah oui ok ! Et c'est beaucoup plus souple à gérer en fait !

Je me permets une autre question, en abusant de ta gentillesse et de ton temps, car la solution que tu m'as trouvée va servir également pour les médias liés à l'article, et peut-être plus tard pour des évolutions...

Le lien généré est de type :http://egypte.webou.net/index.php?section=&article=2

Comme on le voit, "section=" reste vide.

J'ai tenté vainement d'intégrer ceci pour récupérer la section :

$sql3 = "SELECT sections.section_id, sections.section_abbr FROM sections WHERE section_id LIKE '"".$row2[article_section].'";


J'ai placé ça dans le "while" du $row2, j'ai testé ensuite plus haut dans le code, mais rien à faire. J'ai ensuite testé :

$sql3 = "SELECT articles.article_id, articles.article_section, sections.section_id, sections.section_abbr FROM articles LEFT JOIN sections ON article_section=section_id";


Le problème est de connecter article_section (qui comporte "5" par exemple) dans la table "articles", avec section_id (son numéro automatique) et de renvoyer section_abbr de la table "sections" (dans notre exemple : section_id "5" > section_abbr "tem").
Sans cet identifiant de section, une partie du site n'est plus généré (sitemap, etc.).

Je patauge, je rame, je galère... Smiley langue
Salut,

Attention: utiliser une requête SQL dans une boucle PHP, c'est prendre le risque de voir le nombre de requêtes par page exploser, et les performances du site dégringoler, s'il ne se plante pas tout simplement.

Pour récupérer des informations dans plusieurs tables, il faut utiliser les jointures. D'où l'intérêt de normaliser tes tables, aussi.

Dans ce cas précis, j'ai un doute: l'id de la section dont tu as besoin devrait déjà être présent dans les informations relatives à l'article, non? Pour moi, c'est tout simplement le champ "article_section".

Enfin, pour comparer des entiers entre eux, je ne vois pas l'intérêt d'utiliser LIKE. Une simple égalité est sans doute plus indiquée:
"... section_id = ".$article['article_section']."..."
Bonjour Thomas,

J'ai suivi les conseils d'Heoyan et créé une table "intermédiaire" qui fait le lien entre les articles (une table à deux champs).

Cette fois-ci, je voudrais en plus ajouter à l'URL générée l'abbréviation de la section (puisque j'utilise aussi une table "sections").

Table sections
|section_id|section_nom|section_abbr|section_desc|
Ex :
|5|La terre|ter|La terre d'Égypte fascine autant par blabla...|

Table articles
|article_id|article_titre|[...]|article_section|
Ex :
|1|L'île de Philae|[...]|5|

Si je stocke "5" dans articles > article_section, je veux que la requête le compare à sections > section_id et renvoie sections > section_abbr

A noter que par rapport à ma question de départ, ce n'est pas exactement le même souci, puisqu'un article n'est rattaché qu'à une section ! (Mais une section a bien sûr plusieurs articles...)

Ce que je ne comprends pas, c'est comment utiliser le numéro de section indiqué dans "articles" tant que je ne fais pas la boucle while de génération des résultats ?
Pour récupérer l'abréviation de section en plus des données de l'article, tu pourrais par exemple écrire, dans ta première requête:
$query = "SELECT articles.*, sections.section_abbr FROM articles, sections WHERE sections.section_id = articles.article_section AND ...";
$result = mysql_query($query);
while ($article = mysql_fetch_array($result))
{
  # $article est maintenant un tableau contenant tous les champs
  # de la table articles plus le champ section_abbr correspondant.
  ...
}
C'est une autre façon d'écrire la jointure (JOIN). C'est équivalent à ceci:
$query = "SELECT articles.*, sections.section_abbr FROM articles JOIN sections ON sections.section_id = articles.article_id WHERE ...";
montoumes a écrit :
tant que je ne fais pas la boucle while de génération des résultats ?
Justement, il ne faut pas faire une boucle de génération, mais une boucle d'affichage des résultats: d'abord, tu vas chercher dans la base de données tout ce qui t'intéresse en utilisant une requête SQL appropriée, c'est ton résultat. Ensuite tu fais une boucle pour parcourir les enregistrements que la BDD t'a renvoyés et les mettre en forme.

Est-ce que c'est plus clair ?
Bon j'ai cherché un peu plus, et j'ai un problème de position de boucle...


$reperearticle = !empty($_GET['article']) ? intval($_GET['article']) : 0;
if ( $reperearticle > 0 ) { // Si un code article est renseigné dans l'url
	$sql1 = "SELECT articles.*, sections.section_abbr FROM articles, sections WHERE sections.section_id = articles.article_section";
	$result1 = mysql_query($sql1) or die(mysql_error());
	while ($article = mysql_fetch_array($result1))
	{
		if ( mysql_num_rows($result1) > 0 ) { // Si ce code article existe dans la base
			echo "<h3 class='lireaussi'>lire aussi sur ce site</h3>\n" ;
			echo "<p class='lireaussitexte'>Pour compl&egrave;ter la lecture de cet article, vous pouvez lire &eacute;galement sur ce site :</p>\n" ;
			echo "<ul class='lireaussicontent'>\n" ;
			
			$sql2 = "Select article_id, article_titre, article_section from articles, liens_articles where article_id_base = $reperearticle and article_id_lie = article_id";
			$result2 = mysql_query($sql2) or die(mysql_error());						
			
			if ( mysql_num_rows($result2) > 0 ) 
				{ // Si un (ou des) code(s) article sont associé(s) au 1er article
					while ($row2 = mysql_fetch_assoc($result2)) {
					echo "\t<li><a href='index.php?section=".$article['section_abbr']."&article=".$row2['article_id']."' title='Consulter cet article : ".$row2['article_titre']."'>".$row2['article_titre']."</a></li>\n";
				}
			echo "</ul>\n";
			}
		}
	}


Ca provoque 3 fois le bloc "lire aussi sur ce site", avec à chaque fois les deux bons liens, avec les deux bons id d'article, mais avec deux "section=ter" et un "section=die"...
Modifié par montoumes (15 Jul 2008 - 15:56)