# Billetterie associative : réserver une place sans jamais la survendre

> Une association qui organise un événement ponctuel n'a pas besoin d'une billetterie complète, mais doit verrouiller le stock de places au moment critique du paiement.

- Auteur : WordPress Développement
- Publié le : 2021-03-23
- Mis à jour le : 2021-03-23
- Catégorie : Extensions
- URL : https://www.wpmoderne.fr/extensions/billetterie-associative-reserver-place-sans-survendre/

## L’essentiel

- Le stock se décrémente à la confirmation du paiement, pas avant
- Un verrou temporaire évite la double vente en cas de double clic
- wpdb->query avec une clause atomique protège la concurrence

Deux visiteurs qui cliquent sur « réserver » à la même seconde pour la dernière place disponible : c'est le scénario que toute billetterie doit gérer correctement, même une billetterie associative légère montée pour un seul événement ponctuel plutôt qu'une plateforme commerciale complète.

Sans précaution particulière, un code naïf qui vérifie le stock disponible puis décrémente la valeur dans deux requêtes séparées laisse une fenêtre de temps, même brève, pendant laquelle deux visiteurs peuvent lire la même valeur de stock avant que l'un des deux ne la modifie. Résultat : une place vendue deux fois.

## Un stock stocké en option, pas en métadonnée d'article

Pour un événement unique, un simple enregistrement d'option suffit à représenter le stock disponible, sans avoir besoin d'un type de contenu par place :

```
update_option( 'wpm_places_disponibles', 150, false );
```

Le troisième paramètre à `false` indique à WordPress de ne pas charger cette option automatiquement à chaque affichage de page, ce qui reste pertinent puisque la valeur n'est consultée qu'au moment de la réservation, pas sur chaque page du site.

## Décrémenter de façon atomique, directement en SQL

La méthode qui élimine la fenêtre de concurrence consiste à effectuer la lecture et l'écriture du stock en une seule requête SQL, plutôt qu'en deux appels PHP successifs :

```
global $wpdb;

$table  = $wpdb->options;
$places = (int) $_POST['nb_places'];

$lignes_modifiees = $wpdb->query(
    $wpdb->prepare(
        "UPDATE {$table}
         SET option_value = CAST(option_value AS SIGNED) - %d
         WHERE option_name = 'wpm_places_disponibles'
         AND CAST(option_value AS SIGNED) >= %d",
        $places,
        $places
    )
);

if ( 0 === $lignes_modifiees ) {
    wp_send_json_error( array( 'message' => 'Plus assez de places disponibles.' ) );
}
```

La condition `WHERE ... >= %d` dans la même requête garantit que la décrémentation n'a lieu que si le stock restant le permet réellement au moment exact de l'exécution, sans dépendre d'une lecture PHP antérieure qui pourrait déjà être obsolète.

> L'essentiel à retenir : Le stock se décrémente à la confirmation du paiement, pas avant ; Un verrou temporaire évite la double vente en cas de double clic ; wpdb->query avec une clause atomique protège la concurrence

## Réserver avant de confirmer le paiement

Décrémenter le stock dès le clic sur « réserver » pose un autre problème : un visiteur qui abandonne son paiement bloque une place indéfiniment. La solution consiste à distinguer deux états, avec un délai de grâce court porté par un transient.

### Étape 1 : réservation temporaire

```
set_transient( 'wpm_reservation_' . $jeton, $places, 10 * MINUTE_IN_SECONDS );
```

### Étape 2 : confirmation ou libération

- Si le paiement aboutit, la réservation devient définitive et le stock reste décrémenté
- Si le transient expire sans confirmation, une tâche planifiée réintègre les places au stock disponible
- Si le visiteur annule volontairement, la même routine de libération s'applique immédiatement

## Ce que cette architecture ne couvre pas

Cette approche reste pensée pour un événement unique, sans plan de salle ni catégories de places multiples. Une billetterie qui gère plusieurs salles, des tarifs différenciés par catégorie ou des sessions récurrentes justifierait une structure de données plus élaborée, avec une table dédiée par catégorie de place plutôt qu'une simple option globale.

| Étape | Mécanisme | Risque évité |
| --- | --- | --- |
| Vérification du stock | Requête SQL atomique | Survente en cas de clics simultanés |
| Réservation temporaire | Transient avec expiration | Place bloquée indéfiniment |
| Confirmation | Décrémentation déjà appliquée | Double décrémentation |

> Sur une billetterie, mieux vaut une requête SQL un peu moins élégante mais atomique qu'un code PHP lisible qui laisse passer une seconde de concurrence entre la lecture et l'écriture du stock.

## Notre verdict

Pour un événement associatif ponctuel, cette architecture légère évite d'installer une extension de billetterie complète tout en réglant le seul point réellement critique : ne jamais vendre une place qui n'existe plus. La clé tient dans une opération atomique côté base de données, appuyée par un mécanisme de libération automatique des réservations abandonnées.
