8791 sujets

Développement web côté serveur, CMS

Bonjour.

Il y a quelque temps j'avais poser une question pour faire une requête SQL avec un $_GET[''] pour que la requête change en fonction de l'id... J'aimerais faire pareille si c'est possible avec `09` pour simplifier mes pages mais je n'y arrive pas:

SELECT * FROM `09` WHERE id =' . $_GET['id']

J'ai obtenu ca:
SELECT * FROM' . $_GET['tbl'] . 'WHERE id =' . $_GET['id']

C'est le meilleur truck que j'ai fait autrement j'ai de grosse erreur et rien ne s'affiche.
J'ai ce code d'erreur:
Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROMWHERE id =1' at line 1 ) 1


A moins qu'il y est une autre façon de le faire.
Salut,

loixi a écrit :
C'est le meilleur truck que j'ai fait
Smiley lol

C'est tout sauf clair : est-ce que tu veux dire que tu utilises des tables avec des noms sous forme de chiffres... que tu passes en GET dans l'url ?

Admettons (en laissant de côté les failles de sécurité potentielles) !

Il faut au minimum un espace après FROM et avant WHERE et également échapper un tel nom de table !

Ce qui donne :
'SELECT * FROM `' . $_GET['tbl'] . '` WHERE id =' . $_GET['id']
Merci, bas je sais pas comment faire autrement c'est le meilleur truck que j'ai trouver pour que ca marche sans faire 20 pages a chaque fois.
Par contre si il y a un moyen de sécuriser ca serais bien.

Dans l'adresse donne: ?tbl=09&id=1&url=09
tbl: c'est la table 09.
id: 1.
et l'url pour revenir a la page précédente...

Edit: le problème c'est qu'avec ce système ca m'affiche qu'une ligne de ma table Smiley sweatdrop .
J'aimerais rajouter LIMIT 0 , 300. Mais j'ai encore une erreur de syntaxe.
Modifié par loixi (17 Sep 2010 - 19:41)
Salut,

Pour commencer, le mieux est d'essayer la requête qui t'as été conseillée juste au dessus.
'SELECT * FROM `' . $_GET['tbl'] . '` WHERE id =' . $_GET['id']

Et pour sécuriser un "machin" comme ça... C'est clairement pas faisable avec ce système Smiley lol

Tu passes un nom de table dans un GET... Le mec qui pige un minimum le web peut facilement récupérer n'importe quelle donnée de ta base de données en changeant à la main cette valeur. Smiley cligne

D'après ce que je sais, la plupart des SGBD, n'autorise pas les tables qui ne commencent pas par une lettre. Enfin bref, cela ne vient qu'en second plan. Le mieux c'est de préfixer tes tables par une lettre !

A plus.
loixi a écrit :
J'ai trouver tout seule:

SELECT * FROM `' . $_GET['tbl'] . '` LIMIT 0 , 300; WHERE id =' . $_GET['id']


Ben oui, mais non. Là, tu viens de virer le where de ta requete. (Le ';' correspond à la fin).

En plus, il est préférable de mettre le LIMIT en fin :

SELECT * 
FROM `' . mysql_real_escape_string($_GET['tbl']) . '` 
WHERE id =' . mysql_real_escape_string($_GET['id']) .'
ORDER BY 1, 2
LIMIT 0 , 300


Et j'ai ajouté un tri Smiley smile
(Les sauts de lignes sont à retirer).

Sinon, au boulot sur DB2, on me dit toujours : Les "SELECT *" c'est mal, il faut mettre le nom des rubriques accédées !
Modifié par Borak (18 Sep 2010 - 09:15)
Salut,

Borak a écrit :
SELECT * 
FROM `' . mysql_real_escape_string($_GET['tbl']) . '` 
WHERE id =' . mysql_real_escape_string($_GET['id']) .'
ORDER BY 1, 2
LIMIT 0 , 300
Ben oui, mais non. Smiley lol

Le premier mysql_real_escape_string ne sert à rien sur un nom de table : il sert à protéger les données et ici la sécurisation doit avoir lieu avant d'effectuer la requête (même si je ne suis pas sûr que l'ami loixi ait envie de le faire).

Le second mysql_real_escape_string est également inutile puisqu'on peut supposer que l'id de la table est numérique. On pourrait utiliser intval mais idéalement on ne devrait pas du tout avoir de $_GET dans la requête puisqu'encore une fois les tests devraient être effectués en amont.

Pour finir quand on précise une valeur d'id dans la clause WHERE on s'attend logiquement à ne récupérer qu'un seul enregistrement... donc inutile d'utiliser ORDER BY ni même LIMIT.

Borak a écrit :
Sinon, au boulot sur DB2, on me dit toujours : Les "SELECT *" c'est mal, il faut mettre le nom des rubriques accédées !
C'est vrai quel que soit le système de BDD mais encore plus sur DB2 où il n'est pas rare de se retrouver avec des millions d'enregistrements dans les tables. Smiley smile

Au passage, et dans le même ordre d'idée, il est préconisé de ne pas utiliser de nombre dans la clause ORDER BY mais le nom des champs.
Modifié par Heyoan (18 Sep 2010 - 11:13)
Borak a écrit :


Ben oui, mais non. Là, tu viens de virer le where de ta requete. (Le ';' correspond à la fin).

En plus, il est préférable de mettre le LIMIT en fin :

SELECT * 
FROM `' . mysql_real_escape_string($_GET['tbl']) . '` 
WHERE id =' . mysql_real_escape_string($_GET['id']) .'
ORDER BY 1, 2
LIMIT 0 , 300


Et j'ai ajouté un tri Smiley smile
(Les sauts de lignes sont à retirer).

Sinon, au boulot sur DB2, on me dit toujours : Les "SELECT *" c'est mal, il faut mettre le nom des rubriques accédées !

Si j'ai fais comme ca c'est que j'arrivais pas a y mettre après et que quand j'ai mis le ";" ça a marcher.

Ça marche parfaitement avec la requette que j'ai donnée plus haut, ca a été un peut dure a mettre tout au point j'avais parfois des erreurs.

Mais j'aurais bien aimer éviter de mettre le nom de ma table dans l'adresse, mais ca m'évite de faire plusieurs pages a chaque fois. A moins qu'il y est une autre façon de le faire.
loixi a écrit :
j'aurais bien aimer éviter de mettre le nom de ma table dans l'adresse, mais ca m'évite de faire plusieurs pages a chaque fois.
Le problème n'est pas là mais si tu le fais il faut le sécuriser ! On ne devrait pas effectuer une requête en reprenant tel quel des valeurs en GET et encore moins quand l'une de ces valeurs est le nom d'une table. Tu pourrais par exemple avoir un tableau des tables possibles et ne passer en GET que l'index de ce tableau. Il faudrait également vérifier que ton identifiant est bien numérique.

En reprenant tes drôles de noms de tables dont j'ai du mal à voir l'intérêt puisqu'ils te forcent à les échapper dans la requête et qu'on préconise d'utiliser des noms évocateurs (tables et champs) ce qui permet de s'y retrouver quand on revient sur un code 6 mois après, tu pourrais faire quelque chose comme :
if( isset( $_GET['tbl'] ) || isset( $_GET['id'] ) ) {
	$tables = array(
		1 => '01',
		2 => '02',
		3 => '09'
	); // tables possibles
	$table = !empty($_GET['tbl']) ? intval($_GET['tbl']) : 0;
	$id = !empty($_GET['id']) ? intval($_GET['id']) : 0;
	
	$erreurs = array();
	
	// Table incorrecte
	if(! array_key_exists($table, $tables) ) {
		$erreurs[] = 'Table incorrecte.';
	}
	// id incorrect
	if( empty($id) ) {
		$erreurs[] = 'id incorrect.';
	}
	
	// Pas d'erreur -> on effectue la requête
	if( empty($erreurs) ) {
		$sql = 'Select champ1, champ2 From `'. $tables[$table] .'` Where id = '.$id;
		$result = mysql_query($sql);
		// etc.
	} else {	// Sinon on affiche les erreurs
		foreach($erreurs as $erreur) {
			echo '<p class="alerte">'.$erreur."</p>\n";
		}
	}
}

Modifié par Heyoan (18 Sep 2010 - 11:39)
Je n'arrive pas a y faire marcher, comment tu fait pour choisir la table ? Ca me marque juste: Table incorrecte.
Modifié par loixi (18 Sep 2010 - 12:39)
Heyoan a écrit :
Ce qui donne une url sous la forme www.example.com?tbl=3&id=1

Ca j'avais compris mais je comprend pas comment modifier pour afficher le contenu de mes tables et la requête:
Select champ1, champ2 From `'. $tables[$table] .'` Where id = '.$id;

C'est quoi champ1 et champ2 ???
loixi a écrit :
C'est quoi champ1 et champ2 ???
Euh... c'est un exemple de noms de champs à récupérer. Smiley rolleyes
Heyoan a écrit :
Pour finir quand on précise une valeur d'id dans la clause WHERE on s'attend logiquement à ne récupérer qu'un seul enregistrement... donc inutile d'utiliser ORDER BY ni même LIMIT.

Oui, mais j'ai mis un "ORDER" parce qu'il y avait un "LIMIT" avant. Donc, il y avait de forte chance qu'il y ait plusieurs lignes Smiley smile

J'ai un peu de mal à voir une raison valable d'utiliser des noms de tables numériques. Comment on peut arriver à s'y retrouver ?
Modifié par Borak (18 Sep 2010 - 20:15)