-1

I'm building a site that offers a discount based upon a promo code that the user has the option to enter. It's necessary for me to validate that the code exists in our database before processing a new signup. Here's the AJAX call I'm using for validation:

if (promo_code) {
    var returned = true;
    $.ajax({
        type:    "POST",
        url:     "/ajax/validate_promo_code.php",
        data:    {promo_code: promo_code},
        success: function(result) {
            if (result == 0) {
                $('#blank_dialog_popup').html('<span class="message_text_big">Sorry, that promo code is not valid.</span>').addClass('message_warning').css('display', 'block').css('z-index', '1003');
                setTimeout(returnMessageBackground, 3000);
                $('#promo_code').focus();
                returned = false;
            }
        }
    });
    if (returned != true) {
        return false;
    }
}

And here's the entire PHP file I use for validation.

<?php
//ini_set('display_errors',1);
//error_reporting(E_ALL|E_STRICT);
    $db = new Database();
    $promo_code = filter_var(intval($_POST['promo_code']), FILTER_VALIDATE_STRING);
    $check_query = "SELECT id FROM users WHERE promo_code = '$promo_code'";
    $db->query($check_query);
    if ($db->num_rows != 1) {
        return 0;
    } else {
        return 1;
    }
?>

The success field won't execute, even if I comment out every line of code from the PHP file except for "return 0;" and get rid of the "data:" line in the AJAX call, which makes me think there's something dreadfully wrong with my code, but I can't for the life of me figure out what. Thanks for your help!

MarvinLazer
  • 198
  • 2
  • 5
  • 16
  • Also, I hope nobody ever uses the following promo code: `1\'; DELETE FROM users;` please read up on protecting your application from MySQL injection. https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php – OK sure Aug 21 '18 at 09:08

3 Answers3

3

return does not cause a PHP program to write output. You need echo or print for that.


Also, you are trying to read the value of your JS returned variable before you set it.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Thanks! So, ignoring the asynchronous issue, changing the return statement in the PHP file to echo or print would give me what I needed? – MarvinLazer Aug 21 '18 at 09:13
1

First of all as @Quentin stated you need to use echo or print.

Second:

AJAX request as aysnc. That means the code is not executed in order but the success() function is called later on (After the Server responded). What I mean with that is that this part

if (returned != true) {
    return false;
}

Will never be executed since you are changing the value of returned in the success() method which is only executed async.

Here is an example fiddle how to manipulate UI stuff async: https://jsfiddle.net/xpvt214o/663873/

flx
  • 1,560
  • 13
  • 22
  • Gotcha. I see now that this is a really common problem asked by a lot of people who don't understand async yet. Any recommendations for a workaround? The code is now working properly other than the return statement, and I'm having a hard time understanding the link Quentin sent. – MarvinLazer Aug 22 '18 at 18:55
0

So there were a few problems with this code that I figured out with a lot of research. The main one was that I needed to use "async: false" to make the AJAX call asynchronous. I had a hard time understanding the solutions in @Quentin's link. I've changed some things below to make it a little cleaner and clearer, but this is the final, working version of the function.

// Validate promo code, if present.
if (promo_code) {
    var flag = 1;
    $.ajax({
        type:    "POST",
        url:     "/ajax/validate_promo_code.php",
        data:    {promo_code: promo_code},
        async:   false,
        success: function(data) {
            if (data == 0) {
                $('#blank_dialog_popup').html('<span class="message_text_big">Sorry, that promo code is not valid.</span>').addClass('message_warning').css('display', 'block').css('z-index', '1003');
                setTimeout(returnMessageBackground, 3000);
                $('#promo_code').focus();
                flag = 0;
            }
        }
    });
    if (flag == 0) {
        return false;
    }
}

That was the main issue, but I also had some errors in my PHP code. First, I needed to include the code that creates the Database class. Second, I had to sanitize my string input more effectively. Third, my SQL query did not fetch every row that contains the promo code as I intended. And finally, I didn't need the return statement to have any logic in it. Here's the final version.

require_once('../smarty/Authenticate.inc.php');

$db = new Database();
$promo_code = StringInputCleaner($_POST['promo_code']);
$check_query = "SELECT * FROM users WHERE promo_code = '$promo_code'";
$db->query($check_query);
$return = $db->num_rows;

echo $return;

function StringInputCleaner($data) {
    //remove space before and after
    $data = trim($data); 
    //remove slashes
    $data = stripslashes($data); 
    $data = (filter_var($data, FILTER_SANITIZE_STRING));
    return $data;
}

Hopefully this helps somebody!

MarvinLazer
  • 198
  • 2
  • 5
  • 16
  • using `async: false` is reaaaaly bad practice. But in your case i unterstand you using this since it helps to you to progress. Never the less you should try to fix your javascript code to be able to handle async. – flx Aug 23 '18 at 05:48
  • 1
    Here is an example fiddle how to manipulate UI stuff async: https://jsfiddle.net/xpvt214o/663873/ – flx Aug 23 '18 at 06:08
  • This is seriously above and beyond, my friend. Thank you! – MarvinLazer Aug 23 '18 at 21:14