0

I am trying to create a cost estimation form in WordPress using custom code and I am a beginner in PHP, AJAX, and MYSQL so I need help in the below query.

Basically need to create a dependent dropdown for Car Make and Car Model so I have created one dab table call wp_cost_estimation which has id, make, make_id, model. See the below image.

enter image description here

So if the user selects Acura in the next drop down it should show all the Acura models without repetition. I tried the below code. Please correct me where I am wrong.

cost_estimation_template.php

 <select placeholder="Select Make" name="make" id="make">
              <option disabled="" selected="">--Select Make--</option>
              <?php

                    include get_theme_file_path( '/data.php' );
                    $makes = loadMake();

                    foreach ($makes as $make) {
                                    echo "<option id='".$make['id']."' value='".$make['id']."'>".$make['make']."</option>";
                                }
              ?>
            </select>

  <select placeholder="Select Model" name="model" id="model">
              <option disabled="" selected="">--Select Model--</option>

            </select>

data.php

 if(isset($_POST['aid'])) {
    $db = new DbConnect;
    $conn = $db->connect();
    $stmt = $conn->prepare("SELECT model_name FROM wp_cost_estimation WHERE make_id = " . $_POST['aid'] GROUP BY model_name);
    $stmt->execute();
    $models = $stmt->fetchAll(PDO::FETCH_ASSOC);
    echo json_encode($models);
}

 
  function loadMake() {
    $db = new DbConnect;
    $conn = $db->connect();

    $stmt = $conn->prepare("SELECT MIN(id) AS id, make FROM wp_cost_estimation GROUP BY make");
    $stmt->execute();
    $make = $stmt->fetchAll(PDO::FETCH_ASSOC);
    return $make;
}

AJAX Code:

<script type="text/javascript">
    $(document).ready(function(){
        $("#make").change(function(){
            var aid = $("#make").val();
            $.ajax({
                url: '<?php echo get_theme_file_path('/data.php'); ?>',
                method: 'post',
                data: 'aid=' + aid
            }).done(function(model){
                console.log(model);
                model = JSON.parse(model);
                $('#model').empty();
                model.forEach(function(models){
                $('#model').append('<option>' + models.model_name + '</option>')
                })
            })
        })
    })
</script>  

Please help me out.

4
  • what doesn't work ? are you getting any error ? Commented Dec 31, 2020 at 6:58
  • As of now its not showing any errors but it is not even showing result i want Commented Dec 31, 2020 at 7:27
  • I think the problem is here get_theme_file_path('/data.php'). Could you please show what return this function? Commented Dec 31, 2020 at 8:39
  • Also you can see here some example - gist.github.com/devinsays/69a305053e35a10584f94d6011bba2d6 Commented Dec 31, 2020 at 8:41

1 Answer 1

1

If you're using WordPress, you'll definitely want to give the AJAX in Plugins and J.A.jQ Codex a thorough read, you're not really using any of the benefits of WordPress if your existing code.

The two biggest things you'd want to take advantage of here are the wp_ajax_{$action}() hook and the $wpdb class.

The wp_ajax_ (and wp_ajax_nopriv_) hooks allow you to easily run functions with specific actions, and the $wpdb class handles the vast majority (read: all) of the database connection and interactions that you'll need. And you can drop almost all of this in your functions.php file (or a plugin file, or Must Use Plugin file)

I've taken the liberty of setting up a working example here: https://xhynk.com/content-mask/65517584-answer/

Here's what the functions.php file looks like:

function loadMake(){
    global $wpdb;
    return $wpdb->get_results( "SELECT MIN(id) AS id, make FROM cm_test_make_model GROUP BY make" );
}

add_action( 'wp_enqueue_scripts', function(){
    wp_enqueue_script( '65517584', get_stylesheet_directory_uri() . '/assets/scripts/65517584.js', [], filemtime(get_stylesheet_directory() . '/assets/scripts/65517584.js'), true );

    $localize = array( 'ajax_url' => admin_url( 'admin-ajax.php' ) );
    wp_localize_script( '65517584', 'ajax_object', $localize );
});

add_action( 'wp_ajax_load_models', 'load_models' );
add_action( 'wp_ajax_nopriv_load_models', 'load_models' );
function load_models(){
    if( isset($_POST['aid']) ){
        global $wpdb;
        
        $sql = "SELECT model_name FROM cm_test_make_model WHERE make_id = %d GROUP BY model_name";
        $results = $wpdb->get_results( $wpdb->prepare( $sql, array( absint($_POST['aid']) ) ) );

        wp_send_json( $results, 200 );
    } else {
        wp_send_json( array('message', 'aid is required'), 400 );
    }
}

You'll note the loadMake() function uses $wpdb to make the simple query (I also changed the table name to fit mine)

It's also enqueuing the JavaScript file, and localizes it with wp_localize_script() to pass the appropriate AJAX URL to it (this is also how you can pass along other data from PHP to your JS handler).

The last part uses the wp_ajax_ hooks to run the load_models function, and uses $wpdb's helper functions to prepare the statement, and wp_send_json to convert it to JSON, print it out, and then die. (IT IS VERY IMPORTANT TO KILL THE REQUEST WITH DIE/EXIT AFTER RUNNING A FUNCTION VIA AJAX. If you echo out the json manually, you'll need to call die or exit after.)

Below is the enqueued JavaScript file (note, I enqueued this relative to my theme, you may need to change the URL that's enqueued above if yours is in a different location:

jQuery(document).ready(function($){
    $("#make").change(function(){
        var aid = $("#make").val();
        $.ajax({
            url: ajax_object.ajax_url + '?action=load_models',
            method: 'post',
            data: 'aid=' + aid
        }).done(function(models){
            $('#model').empty();
            models.forEach(function(model){
                console.log( model );
                $('#model').append('<option>' + model.model_name + '</option>');
            });
        });
    });
});

You can see the URL is using the localized variable we passed along.

Lastly, I made a simple Page Template that has the selects on it. Note that wp_enqueue_scripts requires wp_head() on the page, and if using the $in_footer option of wp_enqueue_script() you'll need wp_footer() as well:

<?php wp_head(); ?>
<select placeholder="Select Make" name="make" id="make">
    <option disabled="" selected="">--Select Make--</option>
    <?php
        $makes = loadMake();
        foreach( $makes as $make ){
            printf( '<option id="%d" value="%d">%s</option>', $make->id, $make->id, $make->make );
        }
    ?>
</select>

<select placeholder="Select Model" name="model" id="model">
    <option disabled="" selected="">--Select Model--</option>
</select>
<?php wp_footer(); ?>

A bit long-winded (sorry!) but you'll really want to make use of WordPress' ecosystem if you're going to be using it. And again, here's the link to the working example using the code above: https://xhynk.com/content-mask/65517584-answer/ which uses the following database structure: this database structure

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you so much give me some time to implement will let you know if it worked or not.
Thanks thanks alot i can't tell you how important it was for me to complete this by today.
My pleasure, I'm glad I was able to help! Props for being able to move from traditional PHP/Ajax to WordPress's as well - (I know from experience it can be a bit daunting), but once you get the hang of it, it really does make it a lot easier to manage dynamic interactions like this. Cheers!
I hope some day i will be as pro as you are today. Happy New year in advance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.