0

I'm trying to make my own appointment system for WordPress. For this, I created a post type called "appointments". When users select a service from the service list, the available dates and times are listed. When the available date and time are selected and the appointment is created, a meta key named "appointment_datetime" is added for this appointment. Here is where the problem started.

Two different users should not be able to make an appointment for the same service at the same time. Therefore, when a user tries to create an appointment, the following method is used to check whether the date and time he chose are available.

$already_reserved = new WP_Query(array(
    'post_type' => 'appointments',
    'fields' => 'ids',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'datetime',
            'value' => $date_time, // timestamps
            'type' => 'numeric',
            'compare' => '='
        )
    ),
    'tax_query' => array(
        array(
            'taxonomy' => 'services',
            'field' => 'id',
            'terms' => $service_id,
        )
    )
));
if ( !empty($already_reserved->posts) ) {
    $response = 'Sorry, this date is full.';
} else {
    // create new appointment post
    // ...
}

And here is the ajax code I used:

var $response = jQuery('#response');
$('#createnew').click(function () {
    var service = document.getElementById('service').value;
    var datetime = document.getElementById('datetime').value;
    $response.html("<div class='loading'>Waiting...</div>");

    $.ajax({
        type: 'POST',
        url: myajax.ajaxurl,
        data: {
            action: 'new_appoitment',
            service: service,
            datetime: datetime,
            // ... another customer details
        },
        success: function(data, textStatus, XMLHttpRequest) {
            $response.html('');
            $response.append(data);
        }
    });
});

After all; When two different users click the button at the same time, they can create an appointment for the same date and time. Is there any way I can prevent this?

6
  • The likelihood that two users will submit/click at exactly the same time is really small. We're talking milliseconds... What you could do if you wanted to be absolutely certain is create a 'hold' record, a temporary record in the DB that sets a 'date/time' as being held and check that before you allow a user to submit the appointment request. But then, what if two people are selecting the date/time at the exact same time? I think what you really need to do is just run a validation that the date/time is not taken before adding to the database. – Tony Djukic Nov 29 '20 at 3:47
  • Yes, it is really unlikely. However, sometimes I may encounter such a situation during really busy periods. It's actually more than milliseconds. It gives the same result in about 5-6 seconds. @TonyDjukic – Faruk Nov 29 '20 at 19:48
  • I can see a user getting frustrated booking their time slot and then learning it’s no longer available. For user experience I’d consider placing a hold on a date/time, so at least that way you don’t have two users booking a time slot. You could do it using transients. – Tony Djukic Nov 29 '20 at 22:09
  • Well, can you explain this with a short example? @TonyDjukic – Faruk Nov 29 '20 at 22:27
  • Not really; there’s far too many things I don’t know about your system/set-up to even begin addressing this. Are the time slots pre-configured, are they postmeta, are the custom-posts, are they taxonomies, do they even use the WordPress data structure? Is this a third party plugin being used? Is it all entirely custom? – Tony Djukic Nov 30 '20 at 1:32
0

first of all at the end of using a new WP_Query it's good pratice to always use wp_reset_postdata(); to be sure nothing had compromise your database.

$already_reserved = new WP_Query(array(
    'post_type' => 'appointments',
    'fields' => 'ids',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'datetime',
            'value' => $date_time, // timestamps
            'type' => 'numeric',
            'compare' => '='
        )
    ),
    'tax_query' => array(
        array(
            'taxonomy' => 'services',
            'field' => 'id',
            'terms' => $service_id,
        )
    )
  wp_reset_postdata();
));

and to answer your question, why don't use another if when the button is pressed, right before the appointment is set on the database. like so

if ( !empty($already_reserved->posts) ) {
    $response = 'Sorry, this date is full.';
} else {
    // create new appointment post
    // ...
    // the user has everything and click the button
    if ( !empty($already_reserved->posts) ) {
        $response = 'Sorry, this date is no longer available.'; 
    } else {
    // the appointment is set on the database
    }
}

this is supposing that first there is a validation of the date and only after that the user / users press the button to confirm. if the button has a specific function try to edit that function to make this validation before set the appointment on the database.

1
  • Yes, I tried before you post this answer, but it didn't work. I even put a check operation after the whole function was completed but it still didn't work. Different users can add posts at the same time. – Faruk Nov 29 '20 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.