问题
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.
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.
回答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:
来源:https://stackoverflow.com/questions/65517584/dependent-dropdown-in-wordpress