JeuWeb - Crée ton jeu par navigateur
création d'un nouveau joueur - 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 : création d'un nouveau joueur (/showthread.php?tid=7635)

Pages : 1 2 3


RE: création d'un nouveau joueur - didawin - 29-04-2016

(29-04-2016, 02:53 PM)xanthius a écrit : C'est cette histoire de coupure involontaire qui me fait peur..
Car tout est lié même si les données ne sont pas importantes. En gros s'il y a un écart de ligne entre les 3 tables tout foire toutes les tables doivent avoir le même nombre de ligne à un instant T ..
Donc ton concept serait une sécurité en soit, pour éviter tout dérapage dans la procédure..
Du coup, il faudrait faire quelque chose comme ça  :
- Insertion de l'utilisateur dans la table A, utilisation de l'auto incrément.
- Connexion de l'utilisateur, on vérifie s'il est présent dans les tables B et C si ce n'est pas le cas on insert dans ces tables les lignes nécessaire. On utilise l'auto incrément pour l'ID de chacune des nouvelles lignes mais on y placera dans entity id, l'id du joueur provenant de la table A

c'est bien cela que tu préconise ?

Oui c'est bien cela que je pensait, mais Xenos parle ici d'une solution que je connaît pas qui me paraît beaucoup plus intéressante :

Citation :Tu as aussi les transactions, pour éviter d'avoir des "bouts" de données sauvés (tu veux faire 3 requêtes et que les 3 marchent au aucune des 3).

@Xenos: Aurais tu un lien sur une doc ou autre sur le sujet ?


RE: création d'un nouveau joueur - Xenos - 29-04-2016

Citation : c'est bien cela que tu préconise ?
Ce ne doit pas être à moi que la question est posée... Mais ce que tu cherches, je redis, c'est la notion de transaction qui consiste à obliger le serveur SQL à sauver toute les requêtes (de la page) ou aucune. S'il y a une coupure au milieu (déconnexion du client [car sur PHP, cela peut couper l'exécution de la page me semble-t-il], erreur d'une des requêtes, ou autre), alors *toute* la transaction est annulée ("rollback") et *toutes* les modifications qu'elle impliquait ne sont pas sauvegardées.

Donc:
- Ouverture de transaction
- Insertion dans la table A
- Requêtes dans les autres tables
- Validation (commit) de la transaction.

Si tu n'as qu'une seule requête, la transaction n'est pas nécessaire (aka "ouvrir transaction ; requête ; fermer transaction" cela n'apporte pas grand chose). Si tu as plusieurs requêtes, là, oui, cela sert.



Je ne peux pas faire des liens vers une page d'un bouquin papier, mais je pense que tu trouveras facilement un tuto open class room (ou autre) portant sur "Transaction MySQL".


RE: création d'un nouveau joueur - xanthius - 29-04-2016

En cherchant vite fait je suis tombé sur un exemple :
Code PHP :
<?php
$con
=mysqli_connect("localhost","my_user","my_password","my_db");
// Check connection
if (mysqli_connect_errno())
{
echo
"Failed to connect to MySQL: " . mysqli_connect_error();
}

// Set autocommit to off
mysqli_autocommit($con,FALSE);

// Insert some values
mysqli_query($con,"INSERT INTO Persons (FirstName,LastName,Age)
VALUES ('Peter','Griffin',35)"
);
mysqli_query($con,"INSERT INTO Persons (FirstName,LastName,Age)
VALUES ('Glenn','Quagmire',33)"
);

// Commit transaction
mysqli_commit($con);

// Rollback transaction
mysqli_rollback($con);

// Close connection
mysqli_close($con);
?>
C'est de cela que tu parle ?


RE: création d'un nouveau joueur - Xenos - 29-04-2016

Oui. Ca, c'est la partie d'initialisation.
A l'utilisation, cela ressemblera à:

mysqli->startTransaction() // une seule fois, généralement "au plus tôt" (ça peut être juste après la connexion au SQL)

mysqli->query(...) // blabla mes queries

mysqli->commit() // En toute fin de process, genre juste avant de déconnecter le SQL


RE: création d'un nouveau joueur - xanthius - 29-04-2016

Je suis en procédural pour ma part ..
sur le dev de mysql j'ai trouvé ceci qui je semble corrobore ce que tu as dis
Code PHP :
<?php
$link
= mysqli_connect("127.0.0.1", "my_user", "my_password", "sakila");

if (
mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}

mysqli_begin_transaction($link, MYSQLI_TRANS_START_READ_ONLY);

mysqli_query($link, "SELECT first_name, last_name FROM actor LIMIT 1");
mysqli_commit($link);

mysqli_close($link);
?>
Est ce là la bonne procédure ? que je l'applique illico quoi ^^


RE: création d'un nouveau joueur - Xenos - 29-04-2016

Ouep, c'est cela dans la pratique. Mais il faut bien comprendre qu'une transaction n'a d'utilité que si elle englobe *toutes* les requêtes de la page (donc, l'ouvrir juste après la connexion au SQL, dans la foulée, et la fermer tout à la fin, juste avant de déconnecter le SQL). Là, l'exemple est tristement un peu bidon puisqu'une seule requête n'a pas grand intérêt à être en transaction (encore moins un SELECT).


RE: création d'un nouveau joueur - xanthius - 29-04-2016

Donc si on transpose pour mon exemple ça donnerait quelque chose comme ça :
Code PHP :
<?php
$link
= mysqli_connect("127.0.0.1", "my_user", "my_password", "sakila");

if (
mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}

mysqli_begin_transaction($link, MYSQLI_TRANS_START_READ_ONLY);

mysqli_query($link, "INSERT INTO A ( `champs_1`, `champs_2`) VALUES ("val1","val2")");
mysqli_query($link, "INSERT INTO B ( `champs_1`, `champs_2`) VALUES ("val1","val2")");
mysqli_query($link, "INSERT INTO C ( `champs_1`, `champs_2`) VALUES ("val1","val2")");
mysqli_commit($link);

mysqli_close($link);
?>
et avec cela si on a une coupure lors de la procédure et bien tout est annulé c'est bien ça ?


RE: création d'un nouveau joueur - Xenos - 29-04-2016

C'est cela (on passe sous silence les questions d'injections, évidemment; mais je préfère le marquer au cas où d'autres lisent et reprennent cet exemple Wink ).

S'il y a un problème (coupure de réseau, connexion perdue au SQL, etc) alors le "COMMIT" n'aura pas eu lieu et donc, le serveur SQL ne va rien enregistrer: la BDD sera dans l'état initial où elle était. S'il y a une erreur (duplicate id par exemple), charge à toi de la traiter et de poursuivre l'exécution (jusqu'au COMMIT, donc, les modifs seront sauvées) ou de l'arrêter (ROLLBACK, indiquant de ne pas sauvegarder le résultat de la transaction et de repartir de l'état initial du serveur [en pratique, on repart du début de la transaction, qui est fermée par la même occasion me semble-t-il]).

Je ne connais juste pas "MYSQLI_TRANS_START_READ_ONLY", donc à voir ce que fait ce flag.


Okay, d'après la doc PHP:

Citation :MYSQLI_TRANS_START_READ_ONLY: Start the transaction as "START TRANSACTION READ ONLY".

Ce qui, d'après la doc MySQL:

Citation :The READ ONLY restriction prevents the transaction from modifying or locking both transactional and nontransactional tables that are visible to other transactions; the transaction can still modify or lock temporary tables.


Dans ton cas, tu fais des insertions dans des tables, donc tu ne fais pas de la lecture seule. Tu peux soit utiliser le READ_WRITE (cf doc PHP), soit aucun flag (qui, de mémoire, correspond au READ WRITE, mais à vérifier).


Et MyISAM (un des moteurs de stockage de MySQL) ignore les transactions, donc utilise InnoDB partout Wink


RE: création d'un nouveau joueur - xanthius - 29-04-2016

Super alors !
bon ben je vais mettre à jour ma partie inscription ^^


RE: création d'un nouveau joueur - xanthius - 29-04-2016

Edit: ça fonctionne alors que ça ne fonctionnait pas il y a un instant .. J'y comprend rien mais ça fonctionne