JeuWeb - Crée ton jeu par navigateur
Aide sur des conditions - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Aide sur des conditions (/showthread.php?tid=6391)



Aide sur des conditions - Lindis - 20-04-2014

Je solicite votre aide pour faire avancer le shmilblick Smile

Je ne vois pas trop comment vérifier que le membre posséde bien la variété et le nombre de graines qu'il désire planter..
Je vais vous poster mes tables SQL ainsi que le code qui gére la partie ou le membre est censé planter ses graines.

Et peut être quelqun pourra m'aider à y voir plus clair et me faire un exemple de ou poser les conditions car je nage là et cela m'empêche vraiment d'aller plus loin :heu:
Car je vais aussi devoir vérifier que le membre a assez de pots ,de terre etc...

Pour le moment seules 4 variétés de graines sont présentes dans la table


--
-- Table structure for table `tbl_infos_membres`
--

CREATE TABLE `tbl_infos_membres` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` text COLLATE latin1_general_ci NOT NULL,
`argent` varchar(225) COLLATE latin1_general_ci NOT NULL DEFAULT '7000',
`graines_crystal` varchar(225) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`graines_skunk` varchar(225) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`graines_shiva` varchar(225) COLLATE latin1_general_ci NOT NULL DEFAULT '5',
`graines_haze` varchar(225) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`habitation` varchar(10) COLLATE latin1_general_ci NOT NULL DEFAULT '5',
`terreau` varchar(10) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`pot` varchar(10) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`engrais_vegetation` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`engrais_floraison` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`insecticide` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`lampe` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`kit` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`ventilateur` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`chauffage` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`crystal` varchar(30) COLLATE latin1_general_ci NOT NULL,
`skunk` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`shiva` varchar(30) COLLATE latin1_general_ci NOT NULL,
`haze` varchar(30) COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`purple` varchar(30) COLLATE latin1_general_ci NOT NULL,
`jack_herrer` varchar(30) COLLATE latin1_general_ci NOT NULL,
`orange_bud` varchar(30) COLLATE latin1_general_ci NOT NULL,
`big_bang` varchar(30) COLLATE latin1_general_ci NOT NULL,
`budda_cheeze` varchar(30) COLLATE latin1_general_ci NOT NULL,
`white_widow` varchar(30) COLLATE latin1_general_ci NOT NULL,
`critical_kush` varchar(30) COLLATE latin1_general_ci NOT NULL,
`pakistanais` varchar(30) COLLATE latin1_general_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=69 ;


--
-- Table structure for table `niveau1`
--

CREATE TABLE `niveau1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` text COLLATE latin1_general_ci,
`variete` text COLLATE latin1_general_ci NOT NULL,
`taille` text COLLATE latin1_general_ci NOT NULL,
`eau` text COLLATE latin1_general_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=1195 ;


Et le code permettant de planter n germination (qui doit se faire de 0 à 15 cm)



<?php

include "config.php";

if( isset($_POST['inserer']) && $_POST['inserer']=='Semer' )
{
print_r($_POST);
$nombre = isset( $_POST['nombre'] ) ? mysql_real_escape_string($_POST['nombre']) : 0;
$variete = isset( $_POST['variete'] ) ? mysql_real_escape_string($_POST['variete']) : null;

if($variete==null){
$message = 'Vous devez choisir une variété';
} else {

$nb_desired = mysql_escape_string($_POST['nombre']);
$nb = 1;

if ($nb_desired > 400) {

$message = 'Vous ne pouvez pas mettre à germer plus de 400 graines. ';

} else {

while ($nb <= $nb_desired) {

$sql1 = 'INSERT INTO niveau1 VALUES ("", "'.mysql_escape_string($_SESSION['login']).'", "'.mysql_escape_string($variete).'", "0", "5")';
mysql_query ($sql1) or die ('Erreur SQL !'.$sql1.'<br />'.mysql_error());
$message = 'Vous avez enregistré la variété. ';
$nb++;
}

}

header ('Location: index.php?nav=niveau1');

}
}
$message = isset($_GET['message']) ? $_GET['message'] : null;
echo $message;

$sql = 'SELECT graines_crystal, graines_skunk, graines_shiva, graines_haze FROM tbl_infos_membres WHERE login="'.$_SESSION['login'].'"';
$rq = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());
$data = mysql_fetch_array($rq);

mysql_free_result ($rq);
mysql_close ();

$variete = $data['graines_crystal'];
$variete = $data['graines_skunk'];
$variete = $data['graines_shiva'];
$variete = $data['graines_haze'];


?>
<fieldset style='width:400px;'><legend>Placer des graines en <font color='green'>germination</font></legend>
<form action='index.php?nav=placer_en_germin' method='POST'>
<strong>Semer </strong>
<input type = "text" class="imputco" name="nombre" required size="1" value="1">
<strong> graine(s) de </strong>
<select class="imputco" size='1' name='variete'>
<option>crystal</option>
<option>skunk</option>
<option>shiva</option>
<option>haze</option>
</select>
<input type="submit" name="inserer" class="btn_acheter" value="Semer">
</form>
</fieldset>

Voilà, en espérant que quelqun pourra m'aider, je vous remercie et vous souhaite un bon dimanche Smile


RE: Aide sur des conditions - Ekilio - 20-04-2014




RE: Aide sur des conditions - Lindis - 20-04-2014

Merci bien Ekilio.

En fait la variable $variete je pensais la mettre dans <option value="graines_skunk">skunk</option>
Pour que quand le membre remplit le formulaire le script sache quelle variété est visée dans la table de par sa valeur.
En vrai je me suis emmêlé les pinceaux et mon script ne ressemble plus à grand choses avec possiblement des portions de code en trop car oui la requête SELECT que tu cites ne sert à rien étant déjà présente au dessus.

Je plante au niveau du décompte des graines du membre impossible de me mettre la logique en tête c'est confus.

Je ne vois pas trop comment lui décompter le nombre de graines de la variété qu'il va planter et oui il va falloir que je me mette à PDO qui parait moins bordel dans les sources et plus ordonné.

Je ne suis pas doué en PHP bien que je persévere à apprendre il me reste pas mal de zones d'ombre.


RE: Aide sur des conditions - Ekilio - 20-04-2014

Tu finiras par y arriver en PHP, si tu persévères Smile Ce n'est qu'une question de pratique.

Voici un petit exemple de code pour faire le décompte :

Code PHP :
<?php

// Bien entendu, ces deux variables doivent venir du reste de ton script :)
// Dans ce cas, je considère que tu as déjà sécurisé tes variables.
$variete = 'graines_crystal';
$nombre = 233;
$login = mysql_real_escape_string($_SESSION['login']);

$sql = "UPDATE tbl_infos_membres SET $variete = $variete - $nombre WHERE login = $login";
mysql_query($sql);



RE: Aide sur des conditions - Harparine - 20-04-2014

Salut,
Si je peux me permettre une suggestion sur la modélisation de ta base de données, tu devrais fractionner ta table pour avoir un système plus souple au niveau de l'inventaire.
Par exemple, avec 3 tables au lieu d'1 :
- 1 table personnage ou héros, etc.
- 1 table items ou objet avec des champs du type 'id', 'nom', 'description', 'image', 'caractéristique1', 'carac2', etc.
- 1 table pour faire le lien avec des champs du type 'id', 'perso_id', 'item_id', 'num'.
Ainsi, tu pourrais rajouter de nouveaux items sans toucher à la structure de ta base de données, depuis une interface d'administration.
Tu pourrais même envisager de localiser les items selon leur emplacement avec un champ complémentaire dans la table de relation.
@+


RE: Aide sur des conditions - Lindis - 21-04-2014

Bonjour Ekilio je te remercie pour ta réponse, c'est réglé et du coup ça avance Smile

Harparine merci aussi pour ta suggestion Smile
En effet j'aurais du dispatcher ceci en plusieurs parties après réflexion.
En sachant que cette table risque encore de grandir ^^

Mais arrivé à ce stade du développement de Green-paradis si je la recoupe en trois parties cela va devenir problématique te tout les côtés du script (pas mal avancé) Smile

Toutefois si un jour je suis amené à refaire un autre jeu je ne ferais plus la même erreur.

Merci encore à vous deux, et bonne journée.


RE: Aide sur des conditions - Xenos - 21-04-2014

Les entrées utilisateurs


$nombre = isset( $_POST['nombre'] ) ? mysql_real_escape_string($_POST['nombre']) : 0;
$variete = isset( $_POST['variete'] ) ? mysql_real_escape_string($_POST['variete']) : null;

A coup de "if"
Utilise les cast.
Et vérifie la validité des valeurs de façon exhaustive

define('_INDEX_POST_NOMBRE', 'nombre');
define('_INDEX_POST_VARIETE', 'variete');

if (
isset($_POST[_INDEX_POST_NOMBRE])
and isset($_POST[_INDEX_POST_VARIETE])
and ($nombre = (int)($_POST[_INDEX_POST_NOMBRE])) >= _NOMBRE_VALEUR_MIN
and $nombre <= _NOMBRE_VALEUR_MAX
and ($variete = (string)($_POST[_INDEX_POST_VARIETE])) >= _VARIETE_VALEUR_MIN
and $variete >= _VARIETE_VALEUR_MAX)
{
//...
}


La POO

La POO est souvent plus légère dans ce cas-là, puisqu'elle te permettra d'écrire des trucs du genre:

$data = new DataContainer();
$data->add( new DataNombre( new LoadFromPOST('nombre') ) );
$data->add( new DataVariete( new LoadFromPOST('variete') ) );
if ($data->isEverythingOkay())
{
//...
}
Et tous les contrôles de valeurs fileront dans les objets: les contrôles pour s'assurer que tel ou tel truc (données $_POST par exemple) sont définies et valides seront masqués.



Exceptions

if($variete==null){
$message = 'Vous devez choisir une variété';

Préfère l'utilisation des Exceptions.

try
{
if($variete==null)
throw new Exception('Vous devez choisir une variété');
//...
}
catch (Exception $e)
{
var_dump($e);
}

Ou POO (le message de l'exception est caché dans la classe de l'exception):

try
{
if($variete==null)
throw new Exception\VarieteNonChoisie();
//...
}
catch (Exception $e)
{
var_dump($e);
}



Injection

Coté sécurité, ceci est mal venu:

$sql = 'SELECT graines_crystal, graines_skunk, graines_shiva, graines_haze FROM tbl_infos_membres WHERE login="'.$_SESSION['login'].'"';

Si mon login est le suivant:
Code :
" OR 1=1 ORDER BY `graines_crystal` DESC; --

Alors la query devient:

SELECT graines_crystal, graines_skunk, graines_shiva, graines_haze FROM tbl_infos_membres WHERE login="" OR 1=1 ORDER BY `graines_crystal` DESC; --"

Et je récupère les graines de celui ou celle qui a le plus de crystal. Evidemment, on aurait pu faire bien pire, en utilisant le login:
"; DROP DATABASE `nom_de_BDD`; --

Et là, adieu ta BDD...

Solution:
Soit utiliser des requêtes préparées, soit valider proprement chaque donnée avant de l'insérer dans la requête SQL, via un escape string comme tu l'as fait ailleurs.





$rq = mysql_query($sql) or die('Erreur SQL !'.$sql.''.mysql_error());
A "or die", je préfère l'utilisation d'un "if (mysql_error()) throw new Exception(...)". Le "or die" est assez pesant, et te donne très peu de contrôle sur comment rattraper une erreur.




Simplifier ses requêtes

Pense à simplifier les requêtes SQL, ou à défaut, à les regrouper.

while ($nb <= $nb_desired)
{
$sql1 = 'INSERT INTO niveau1 VALUES ("", "'.mysql_escape_string($_SESSION['login']).'", "'.mysql_escape_string($variete).'", "0", "5")';
mysql_query ($sql1) or die ('Erreur SQL !'.$sql1.''.mysql_error());
$message = 'Vous avez enregistré la variété. ';
$nb++;
}

Regroupé:

$message = 'Vous avez enregistré la variété. ';
$inserts = array();
while ($nb <= $nb_desired)
{
$inserts[] = '("", "'.mysql_escape_string($_SESSION['login']).'", "'.mysql_escape_string($variete).'", "0", "5")';
$nb++;
}
$sql1 = 'INSERT INTO niveau1 VALUES '.implode(',', $inserts);
mysql_query ($sql1) or die ('Erreur SQL !'.$sql1.''.mysql_error());

Faire N requêtes "INSERT" est assez long: préfère la syntaxe de INSERT permettant d'insérer plusieurs données d'un coup.

Encore mieux:


$message = 'Vous avez enregistré la variété. ';
$inserts = array_fill(0, $nb_desired, '(DEFAULT, "'.mysql_escape_string($_SESSION['login']).'", "'.mysql_escape_string($variete).'", 0, 5)';
$sql1 = 'INSERT INTO niveau1 VALUES '.implode(',', $inserts);
mysql_query($sql1)
if (mysql_error())
throw new Exception('Erreur SQL !'.$sql1.''.mysql_error());



Location:

Double toujours tes "location:" par un lien, au cas où le navigateur ne suive pas.

header ('Location: index.php?nav=niveau1');
echo('<a href="index.php?nav=niveau1">Niveau 1</a>');
Aussi, attention aux "index.php?nav=..." car ils sont parfois sensibles à l'injection. Ils sont aussi assez moche dans la barre d'URL, mais c'est secondaire.


Injection cliente
L'injection ne se fait pas que dans la BDD: elle se fait aussi chez le visiteur.
Considère que tout ce que ton serveur émet doit être valide.
Ici, supposons que j'envoie le lien suivant:
Code :
index.php?message=<script>alert(document.cookie);</script>

Alors ce code:

$message = isset($_GET['message']) ? $_GET['message'] : null;
echo $message;

Va émettre ceci au visiteur:
<script>alert(document.cookie);</script>

Si jamais j'envoyais ce lien à une victime, et qu'au lieu d'un "alert()" j'utilisais autre chose pour m'envoyer la valeur de "document.cookie", alors je pourrai connaitre le cookie de ma victime, et accéder à son compte.



Mysql_* est déprécié
Utilise, à la place, mysqli ou PDO.



Note finale: il est tard, je suis creuvé, y'a peut-être une ou deux conneries dans ce post, que les autres corrigent si besoin Smile


RE: Aide sur des conditions - Lindis - 23-04-2014

Xenos je viens de prendre connaissance de ta réponse qui est je te remercie on ne peut plus explicite (et immense, pour aider au mieux à comprendre) Smile

J'ai lu tout ça, ce qui m'évitera à l'avenir de refaire les mêmes erreurs. ; la source du jeu va être refaite en totalité avec des requêtes en "mysqli" et/ou PDO à voir Smile

Pour le moment avec mes deux collègues (équipe récemment montée) nous nous contentons d'écrire un cahier des charges, ce qui n'avait jamais été fait jusque là.
Nous allons aussi partager nos nombreuses idées sur des fonctionnalités envisagées et les noter au clair afin de savoir sur quoi partir exactement et ne pas avoir à rattacher à chaque fois des bouts de codes au besoin comme j'ai pu le faire (la cause de mon embrouillage de cerveau) Smile

Dés que possible nous vous tiendrons au courant quand la reconstruction aura débutée et un peux avancée.

Dans cette attente je te remercie de ton long message à cette heure tardive, et te souhaite une bonne fin de journée.


RE: Aide sur des conditions - Xenos - 23-04-2014

Refait pas tout en cours de route pour passer à du PDO Wink Passer à mysqli sera très simple (99% du temps, il suffit d'ajouter un "i" XD), alors que PDO risque d'entrainer pas mal de changements.

Et welcome, you are Smile