Bonjour,
je poste mon problème dans la section PHP, car je ne sais pas vraiment si la solution viendra du PHP ou du SQL.
J'ai un projet qui propose des événements, sur lesquels on peut réserver des places. Chaque événement à un nombre de réservations maximum ainsi qu'un nombre de réservations maximum par utilisateur.
Lorsqu'un utilisateur pose une réservation, je vérifie que le nombre ce place restantes sur l'événement est suffisant pour accueillir sa réservation (en plus de vérifier qu'il ne dépasse pas sa limite de réservations pour cet événement).
Si le nombre de place qu'il réserve est supérieur au nombre de places restantes sur l'événement, rien ne se passe.
Le problème est que aujourd'hui, sur un événement très prisé, 3 réservations ont été effectuées
à la même seconde ! Avant ces 3 réservations, le nombre de réservations sur l'événement était de 6, pour un maximum de 7 places disponibles. Donc évidemment, le formulaire préalable leur a permis de poster une demande pour 1 place. Et la requête d'insertion s'est faite à la même secondes, passant le nombre de réservations pour cet événement à 9, pour un maximum de 7.
Voici mon code PHP faisant les vérifications juste avant l'insertion :
// On va vérifier combien de réservations pour cet événement ont déjà été faites
$current_bookings = get_value_from_query(sprintf("SELECT SUM(booking_seats) FROM " . TABLES__BOOKINGS . " WHERE booking_event_id = '%d'", $clean['booking_event_id']));
if(!$current_bookings) {
$current_bookings = 0;
}
$max_seats_available_for_event = $max_seats_available - $current_bookings;
if($max_seats_available_for_event <= $max_seats_available_for_user) {
$max_seats_available = $max_seats_available_for_event;
}
else {
$max_seats_available = $max_seats_available_for_user;
}
if($clean['booking_seats'] <= $max_seats_available) {
sql_query(sprintf("INSERT INTO " . TABLES__BOOKINGS . " (booking_event_id, booking_user_id, booking_datetime, booking_seats, booking_status) VALUES('%d', '%d', NOW(), '%d', 0)", $clean['booking_event_id'], $clean['booking_user_id'], $clean['booking_seats']));
$clean['booking_id'] = mysql_insert_id();
}
$clean['booking_seats'] est le nombre de place demandées par l'utilisateur au moment de sa réservation (pour cet événement, l'utilisateur ne peut demander qu'une seule place).
Le problème est que lorsque mes 3 utilisateurs ont soumis le formulaire à la même seconde, $max_seats_available était bien supérieur ou égal au nombre de places demandées, et donc leur réservation à été insérée.. Et je me retrouve donc avec 9 réservations pour un événement ne proposant que 7 places : )
Je cherche donc des solutions, PHP ou SQL. J'ai pensé au LOCK TABLE de mysql, mais cela ne résoudra pas le problème, la requête sera en queue et passera ensuite. Ou alors je lock la table juste avant ma première requete qui va chercher le nombre de places encore disponibles pour l'évènement, et je la delock après l'insertion ? Si le mon script rencontre un LOCK en SQL, il freeze le temps que la table soit DELOCK ?
Si vous voyez une autre solution, je suis preneur : )