Update InnerHTML (Echo PHP) Value on Button Click [duplicate] - javascript

This question already has answers here:
What is the difference between client-side and server-side programming?
(3 answers)
Closed 9 months ago.
I am still in beginner's level of WordPress and PHP. I already doing my research in stackoverflow but because of my low-level understanding, I can't find the solution for the problem I have.
I use WordPress as CMS for my website. I use PHP echo for showing the average rating value of a user review plugin. It shows fine. But after a visitor insert his/her own rating and click submit button, the average rating value didn't update until the page is refreshed. How to automatically update the average rating value after the submit button clicked without having to refresh the page?
<script type="text/javascript">
var userRating = <?php echo rmp_get_avg_rating( $postID ); ?> ;
document.getElementById("div-rating").innerHTML = userRating;
</script>
This is the submit button class created by the plugin to trigger User Submission.
rmp-rating-widget__submit-btn rmp-btn js-submit-rating-btn rmp-rating-widget__submit-btn--visible
This is the PHP function I need to echo.
public function load_results() {
if ( wp_doing_ajax() ) {
// array with vote count, ratings and errors
$data = array(
'voteCount' => false,
'avgRating' => false,
'errorMsg' => '',
);
$post_id = intval( $_POST['postID'] );
$nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : false;
// security check
if( ! $post_id ) {
$data['errorMsg'] = esc_html__( 'You cannot rate a web page without an id!', 'rate-my-post' );
echo json_encode( $data );
die();
}
$nonce_check = $this->has_valid_nonce( $nonce );
if( ! $nonce_check['valid'] ) {
$data['errorMsg'] = $nonce_check['error'];
echo json_encode( $data );
die();
}
$vote_count = rmp_get_vote_count( $post_id );
$sum_of_ratings = rmp_get_sum_of_ratings( $post_id );
$average_rating = rmp_calculate_average_rating( $sum_of_ratings, $vote_count );
if ( $average_rating ) { // post has been rated
$data['voteCount'] = $vote_count;
$data['avgRating'] = $average_rating;
} else { // no ratings so far
$data['voteCount'] = 0;
$data['avgRating'] = 0;
}
echo json_encode( $data );
};
die();
}
Thank you for your help.

Without refreshing the webpage, you can take the data on the server by using XMLHttpRequest object on client side. You can find a lot of implementations ( such as
XMLHttpRequest, Fetch API) which help you for communicating with the server from client side without refreshing page.
If you want to use a different technology ( Socket.io ), web sockets can meet your needs on this problem.

Related

How to dynamically pass an array of values to a <select> field in Contact Form 7?

According to the official Contact Form 7 docs, it is possible to pass a a default value to CF7 from the shortcode, in this way:
// field in CF7 in Wordpress admin area
[email* destination-email default:shortcode_attr]
// shortcode in a Wordpress php template
[contact-form-7 id="123" title="Contact Form" destination-email="xxxxxx#example.com"]
// function in functions.php
add_filter( 'shortcode_atts_wpcf7', 'custom_shortcode_atts_wpcf7_filter', 10, 3 );
function custom_shortcode_atts_wpcf7_filter( $out, $pairs, $atts ) {
$my_attr = 'destination-email';
if ( isset( $atts[$my_attr] ) ) {
$out[$my_attr] = $atts[$my_attr];
}
return $out;
}
This works for a simple text field, but I need to pass an array of values to a <select> field and use them as <option>s inside it; I've tried to modify a bit this code, but apparently it isn't working, or at least I've not been able to.
Is it possible to use the shortcode to send dynamic data to CF7 even if not a single plain text like this?
If not, I'm open to every other kind of solution, even if it involves another method, or some additional plugin; is there some other way to dynamically send an array of values to <select> fields in Contact Form 7?
These values are data queried from the database (such as post names, custom fields, and so on), so they need to come from php first even if there is a solution that involves javascript.
Here's an example of a form tag I've used for getting US States. This is a <select> generated from an array. This is probably more along the lines of what you want to do.
You can see that I also use the usermeta billing_state to pre-select the choice.
With that said, you should also be able to use this same method to create a select tag that performs any WP_Query and puts the results into an option tag.
<?php
add_action('wpcf7_init', function (){
wpcf7_add_form_tag( array('dd_states', 'dd_states*'), 'cf7_state_dropdown' , true );
});
function cf7_state_dropdown($tag) {
$tag = new WPCF7_FormTag( $tag );
$atts = array();
$validation_error = wpcf7_get_validation_error( $tag->type );
$class = wpcf7_form_controls_class( $tag->type );
if ( $validation_error ) {
$class .= ' wpcf7-not-valid';
}
$atts['class'] = $tag->get_class_option( $class );
$atts['aria-required'] = 'true';
$atts['aria-invalid'] = $validation_error ? 'true' : 'false';
$atts = wpcf7_format_atts( $atts );
// Get User ID and Billing State from DB
$userid = get_current_user_id();
$user_state = get_user_meta($userid, 'billing_state', true);
$states = array ( 'FL'=>'Florida','AL'=>'Alabama','AK'=>'Alaska','AZ'=>'Arizona','AR'=>'Arkansas','CA'=>'California','CO'=>'Colorado','CT'=>'Connecticut','DE'=>'Delaware','DC'=>'District of Columbia','GA'=>'Georgia','HI'=>'Hawaii','ID'=>'Idaho','IL'=>'Illinois','IN'=>'Indiana','IA'=>'Iowa','KS'=>'Kansas','KY'=>'Kentucky','LA'=>'Louisiana','ME'=>'Maine','MD'=>'Maryland','MA'=>'Massachusetts','MI'=>'Michigan','MN'=>'Minnesota','MS'=>'Mississippi','MO'=>'Missouri','MT'=>'Montana','NE'=>'Nebraska','NV'=>'Nevada','NH'=>'New Hampshire','NJ'=>'New Jersey','NM'=>'New Mexico','NY'=>'New York','NC'=>'North Carolina','ND'=>'North Dakota','OH'=>'Ohio','OK'=>'Oklahoma','OR'=>'Oregon','PA'=>'Pennsylvania','RI'=>'Rhode Island','SC'=>'South Carolina','SD'=>'South Dakota','TN'=>'Tennessee','TX'=>'Texas','UT'=>'Utah','VT'=>'Vermont','VA'=>'Virginia','WA'=>'Washington','WV'=>'West Virginia','WI'=>'Wisconsin','WY'=>'Wyoming');
$output = '<span class="wpcf7-form-control-wrap '.sanitize_html_class( $tag->name ).'"><select name="state" id="state" '.$atts.'>';
$output .= "<option value=\"\"> - - Choose State - - </option>";
foreach ($states as $abbrev=>$state){
$selected = ($user_state == $abbrev) ? ' selected="selected"' : '';
$output .= '<option value="'.$abbrev.'"'. $selected .'>'.$state.'</option>';
}
$output .= "</select></span>";
$output .= $validation_error;
return $output;
}

Woocommerce live calculation : qty x get_meta('_value') = final value

Here we are talking about selling products (especially pastry or food) in bulk unit / unit / or kg.
All measurements are known weight and quantity,Therefore we must be able to estimate which product in kg will have how many units.
So I created an example of products just to test in woocommerce,
I managed to realize my idea to estimate minimum qty of pieces (or any unit) per kg using a useful piece of code found here.
(1) I put it in a Snippet.
After that I started reading and trying to understand and follow the logic behind the code.
(2) Add some fonctions. just duplicated a few lines.. some copy / paste..
(3) Try to put the same functions in product page (in progress no solution found)
Update 09/12/2019
Code revised no more internal error
// Backend: Add and display a custom field for simple and variable products
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_price_field_to_general_product_data' );
function add_custom_price_field_to_general_product_data() {
global $product_object;
echo '<div class="options_group hide_if_external">';
woocommerce_wp_text_input(array(
'id' => '_min_unit_price',
'label' => __('Min Unit price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')',
'description' => __('Enter the minimum unit price here.', 'woocommerce'),
'desc_tip' => 'true',
'value' => str_replace('.', ',', $product_object->get_meta('_min_unit_price') ),
'data_type' => 'price'
));
// My custom field "Min price unit prefix"
woocommerce_wp_text_input(array(
'id' => '_min_unit_prefix',
'label' => __('Min Unit prefix', 'woocommerce'),
'description' => __(' Enter prefix unit price here.', 'woocommerce'),
'desc_tip' => 'true',
'value' => str_replace('.', ',', $product_object->get_meta('_min_unit_prefix') ),
'data_type' => 'texte'
));
// My custom field "Estimated quantity"
woocommerce_wp_text_input(array(
'id' => '_estimated_quantity',
'label' => __('Estimated Quantity', 'woocommerce'),
'description' => __('Enter the quantity here.', 'woocommerce'),
'desc_tip' => 'true',
'value' => str_replace('.', ',', $product_object->get_meta('_estimated_quantity') ),
'data_type' => 'price'
));
echo '</div>';
}
// Backend: Save the custom field value for simple and variable products
add_action( 'woocommerce_admin_process_product_object', 'save_product_custom_price_field', 10, 1 );
function save_product_custom_price_field( $product ) {
if ( isset($_POST['_min_unit_price']) ) {
$product->update_meta_data( '_min_unit_price', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_min_unit_price'] ) ) ) );
}
if ( isset($_POST['_min_unit_prefix']) ) {
$product->update_meta_data( '_min_unit_prefix', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_min_unit_prefix'] ) ) ) );
}
if ( isset($_POST['_estimated_quantity']) ) {
$product->update_meta_data( '_estimated_quantity', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_estimated_quantity'] ) ) ) );
}
}
// Frontend variable products: Display the min price with "From" prefix label
add_filter( 'woocommerce_variable_price_html', 'custom_min_unit_variable_price_html', 10, 2 );
function custom_min_unit_variable_price_html( $price, $product ) {
if( $min_unit_price = $product->get_meta('_min_unit_price') ){
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $min_unit_price ) ) );
$price .= $product->get_meta('_min_unit_prefix');
}
return $price;
}
// Frontend simple products: Display the min price with "From" prefix label
add_filter( 'woocommerce_get_price_html', 'custom_min_unit_product_price_html', 10, 2 );
function custom_min_unit_product_price_html( $price, $product ) {
if( $product->is_type('simple') && $min_unit_price = $product->get_meta('_min_unit_price') ){
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $min_unit_price ) ) );
$price .= $product->get_meta('_min_unit_prefix');
}
return $price;
}
// Display the cart item weight in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_custom_item_data', 10, 2 );
function display_custom_item_data( $cart_item_data, $cart_item ) {
if ( $cart_item['data']->get_weight() > 0 ){
$cart_item_data[] = array(
'name' => __( 'Weight subtotal', 'woocommerce' ),
'value' => ( $cart_item['quantity'] * $cart_item['data']->get_weight() ) . ' ' . get_option('woocommerce_weight_unit')
);
}
// Display the cart item "estimated quantity" in cart and checkout pages
if ( $cart_item['data']->get_meta('_estimated_quantity') ){
$cart_item_data[] = array(
'name' => __( 'Estimated quantity ', 'woocommerce' ),
'value' => ( $cart_item['quantity'] * $cart_item['data']->get_meta('_estimated_quantity') )
);
}
return $cart_item_data;
}
// Save and Display the order item weight (everywhere)
add_action( 'woocommerce_checkout_create_order_line_item', 'display_order_item_data', 20, 4 );
function display_order_item_data( $item, $cart_item_key, $values, $order ) {
if ( $values['data']->get_weight() > 0 ){
$item->update_meta_data( __( 'Weight subtotal', 'woocommerce' ), ( $item['quantity'] * $values['data']->get_weight() ) . ' ' . get_option('woocommerce_weight_unit') );
}
}
Now, I need help to understand how
Estimated quantity: <? Php echo get_post_meta (get_the_ID (), '_estimated_quantity', true); ?>
can Update in real time with the quantity of add_to_cart.
the formula must be extremely simple in jQuery or javascript ?
_estimated_quantity * quantity.
That all I need now. To show to costumer how much they can get piece of cakes (or any others things) in 1 or xx kg
So I put a 15 or xx (approximate value) in backend.
I hope it makes sense for you.
For information I use clean install wordpress + elementor + elementor hello theme + woocommerce.
update 09/12/2019
I corrected the last php error.
I would like to thank Snuwerd for his support and considerable help without him I will not have the courage to throw myself into the world of php code I learned a lot.
Thank you again
Welcome to Stack Overflow!
To answer your questions:
"Verify that the code is valid"
The code looks quite good (especially if this is really your first time messing with PHP)
"and (code) does not create problems in future woocommerce updates."
This question is really hard to answer.
"Now I am trying to put these two lines of information in the product page. via shortcode? or php again ?"
Probably with more filters/actions, like you have done in the current code. And if that doesn't seem possible, maybe by altering/overriding some template(s). Shortcodes don't necessarily make much sense, unless you want to insert the data into content area's in the backend when adding/editing products.
"Also improve the code"
This doesn't seem necessary.
"and add a prefix to Estimated Quantity."
Can you elaborate on what you mean by this?
ps. I am probably off to bed soon, so I'll check again tomorrow.
Update
I send qty and product_id to the server with AJAX and then the server gives back qty * _estimated_quantity;
To get qty from the box on your screen and to set the right value in Estimated quantity, I need you to make a screenshot of their code. Open the page in Google Chrome, right click > inspect element on the quantity box and then make a screenshot of the code in the Elements tab. Also do the same for the Estimated quantity box (that has 15 in it in the screenshot).
I also assume your website is located on the root of your domain. So on www.example.com and not on www.example.com/wordpress/ (The Ajax call needs the right location).
You can add this PHP to your functions.php
<?php
add_action("wp_ajax_product_get_estimated_quantity", "product_get_estimated_quantity"); // calls our function if user is logged in
add_action("wp_ajax_nopriv_product_get_estimated_quantity", "product_get_estimated_quantity"); // calls our function if user is not logged in, we do not do any security checks on which user etc though, but I don't think it's relevant in our case.
function product_get_estimated_quantity () {
error_log('Snuwerd: Ajax call for estimated quantity is being called correctly.');
$product_id = $_REQUEST["product_id"];
if (!is_numeric($product_id)) { // check if really a number, for security purposes
die();
}
$qty = $_REQUEST["qty"];
if (!is_numeric($qty)) { // check if really a number, for security purposes
die();
}
// No need to get product object, can get metadata directly with get_post_meta
// // get estimated_quantity per kg by product_id
// $args = array(
// 'include' => array( $product_id ),
// );
// $products = wc_get_products( $args );
// foreach ($products as $product) {
// }
// echo $product->get_id();
$estimated_quantity_per_kg = get_post_meta( $product_id, '_estimated_quantity', true);
// $estimated_quantity_per_kg = 15; // this line is only for my local testing, since my products dont have _estimated_quantity meta
echo ((int) $estimated_quantity_per_kg) * ((int) $qty);
error_log('Snuwerd: Ajax call for estimated quantity returned to single-product page.');
die();
}
?>
And add this javascript/jquery anywhere you can (assuming that you know how to, its also easy to find out with google (How to add javascript to Wordpress)).
console.log('Snuwerd: Code planted in document.ready');
jQuery(document).ready(function($) {
console.log('Snuwerd: JS code is being loaded.');
if( $('body.single-product').length) { // if on a single product page
console.log('Snuwerd: We are on the single product page');
$( document ).on( 'change', '.quantity input[type=number]', function() { // selector for the qty box is probably already correct
var qty = $( this ).val();
// var product_id = $(this).closest('.product').attr('id');
// product_id = product_id.split('-');
// product_id = product_id[1];
var product_id = get_current_post_id();
console.log('Snuwerd: quantity changed. Sending ajax call with qty'+qty+' and product_id'+product_id);
jQuery.ajax({
type : "post",
dataType : "json",
url : '/wp-admin/admin-ajax.php', // only works if Wordpress is installed in root of your domain. if you installed in www.example.com/wordpress/, then add /wordpress/ before this
data : {action: "product_get_estimated_quantity", product_id : product_id, qty: qty},
success: function(response) {
console.log('Snuwerd: Ajax call returned succesfully');
// right click -> inspect element to find the right selector for estimated quantity (the 15 from your photoshop)
response = parseInt(response);
console.log('Snuwerd: Ajax call returned succesfully with value '+response);
$('#snuwerd > div').html('Estimated quantity: ' + response);
}
});
return false;
});
}
function get_current_post_id() {
var page_body = $('body');
var id = 0;
if(page_body) {
var classList = page_body.attr('class').split(/\s+/);
$.each(classList, function(index, item) {
if (item.indexOf('postid') >= 0) {
var item_arr = item.split('-');
id = item_arr[item_arr.length -1];
return false;
}
});
}
return id;
}
});
In case you want to know how I added the javascript, i made a file in child-theme-directory/js/child.js.
Then added the Jquery to it. And then I added this to functions.php:
function theme_enqueue_child_scripts() {
error_log('Snuwerd: js script being added in theme_enqueue_child_scripts.');
$file = '/js/child.js';
$cache_buster = date("YmdHis", filemtime( get_stylesheet_directory() . $file )); // no uri
wp_enqueue_script( 'child', get_stylesheet_directory_uri() . $file, array( 'jquery' ), $cache_buster, true ); // true = footer
}
add_action( 'wp_enqueue_scripts', 'theme_enqueue_child_scripts' );
Update
I added the selector for the Estimated quantity field in the javascript, and the quantity selector was already correct, so please re-copy the javascript.
I looked at the screenshot where you add in JS and PHP, but the way you add PHP is not good enough for this PHP. Where you add PHP in the screenshot, it only counts for that page and it needs to be sidewide. The Ajax call will not be able to access PHP that is added to a specific page. If Elementor doesn't have a side wide place to add PHP and if you don't want to change the functions.php of your theme, then maybe you can use this plugin: https://wordpress.org/plugins/my-custom-functions/ . Also, don't forget to actually add the PHP I provided, I didn't see it in your JS/PHP screenshot.
Update
I added some debug messages to find out what parts work. Can you enter the PHP code that is meant for functions.php into your site again and also the JS code.
After this open your product page in Google Chrome and press ctrl+shift+i to open developer tools window. Now change the quantity by pressing the arrows in the number box on the page. There should be a few messages in the Console tab in the developer tools window. Can you paste a screenshot of the console here?
If nothing appears in this console, please check that you're not having cache problems > go to Network Tab in developer tools window and check the disable cache checkbox and then refresh the page and try again.
Next, also check the PHP error log, if you don't know how to check it, please learn about PHP error logging here: https://www.loggly.com/ultimate-guide/php-logging-basics/
In the error log search for Snuwerd and show those lines to me as well.

(populate dropdown in contact form 7 getting this error - Warning: array_keys() expects parameter 1 to be array, null given in

Ok where to start, I will try and explain as much as I can.
I am using wordpress with contact form 7 and I am trying to populate 3 dropdown items on the contact form, I found some code that I was able to use with no problem but the problem with this was that it was getting the information from a excel file, the file is now to big and will not run on my website anymore so I would like to get the information from my database now.
I have made a table in my database "vehicle_information" with 3 columns "vehicle_type", "vehicle_make", vehicle_model"
I have code in my functions.php and code in my footer to be able to use the cf7 shortcodes.
Code from funtions.php
function ajax_cf7_populate_values() {
//MySQLi information
$db_host = '***';
$db_username = '***';
$db_password = '***';
$vehicles_makes_models = array();
//connect to mysqli database (Host/Username/Password)
$connection = mysqli_connect($db_host, $db_username, $db_password) or die('Error ' . mysqli_error());
//select MySQLi dabatase table
$vehicles_makes_models = mysqli_select_db($connection, 'vehicle_information') or die('Error ' . mysqli_error());
$sql = mysqli_query($connection, 'SELECT * FROM vehicle_type');
while($row = mysqli_fetch_array($sql)) {
$vehicles_makes_models[$row[0]][$row[1]][] = $row[2]; }
}
// setup the initial array that will be returned to the the client side script as a JSON object.
$return_array = array(
'vehicles' => array_keys($vehicles_makes_models),
'makes' => array(),
'models' => array(),
'current_vehicle' => false,
'current_make' => false
);
// collect the posted values from the submitted form
$vehicle = key_exists('vehicle', $_POST) ? $_POST['vehicle'] : false;
$make = key_exists('make', $_POST) ? $_POST['make'] : false;
$model = key_exists('model', $_POST) ? $_POST['model'] : false;
// populate the $return_array with the necessary values
if ($vehicle) {
$return_array['current_vehicle'] = $vehicle;
$return_array['makes'] = array_keys($vehicles_makes_models[$vehicle]);
if ($make) {
$return_array['current_make'] = $make;
$return_array['models'] = $vehicles_makes_models[$vehicle][$make];
if ($model) {
$return_array['current_model'] = $model;
}
}
}
// encode the $return_array as a JSON object and echo it
echo json_encode($return_array);
wp_die();
// These action hooks are needed to tell WordPress that the cf7_populate_values() function needs to be called
// if a script is POSTing the action : 'cf7_populate_values'
add_action( 'wp_ajax_cf7_populate_values', 'ajax_cf7_populate_values' );
add_action( 'wp_ajax_nopriv_cf7_populate_values', 'ajax_cf7_populate_values' );
Code from my footer
<script>
(function($) {
// create references to the 3 dropdown fields for later use.
var $vehicles_dd = $('[name="vehicles"]');
var $makes_dd = $('[name="makes"]');
var $models_dd = $('[name="models"]');
// run the populate_fields function, and additionally run it every time a value changes
populate_fields();
$('select').change(function() {
populate_fields();
});
function populate_fields() {
var data = {
// action needs to match the action hook part after wp_ajax_nopriv_ and wp_ajax_ in the server side script.
'action' : 'cf7_populate_values',
// pass all the currently selected values to the server side script.
'vehicle' : $vehicles_dd.val(),
'make' : $makes_dd.val(),
'model' : $models_dd.val()
};
// call the server side script, and on completion, update all dropdown lists with the received values.
$.post('<?php echo admin_url( 'admin-ajax.php' ) ?>', data, function(response) {
all_values = response;
$vehicles_dd.html('').append($('<option>').text(' -- choose vehicle -- '));
$makes_dd.html('').append($('<option>').text(' -- choose make -- '));
$models_dd.html('').append($('<option>').text(' -- choose model -- '));
$.each(all_values.vehicles, function() {
$option = $("<option>").text(this).val(this);
if (all_values.current_vehicle == this) {
$option.attr('selected','selected');
}
$vehicles_dd.append($option);
});
$.each(all_values.makes, function() {
$option = $("<option>").text(this).val(this);
if (all_values.current_make == this) {
$option.attr('selected','selected');
}
$makes_dd.append($option);
});
$.each(all_values.models, function() {
$option = $("<option>").text(this).val(this);
if (all_values.current_model == this) {
$option.attr('selected','selected');
}
$models_dd.append($option);
});
},'json');
}
})( jQuery );
The problem is I am still learning and this is the first time I have had to use this funtion.
and I am getting an error on my website
Warning: array_keys() expects parameter 1 to be array, null given in /customers/4/0/0/motobid.co.uk/httpd.www/wp-content/themes/storevilla-child/functions.php on line 38 {"vehicles":null,"makes":[],"models":[],"current_vehicle":false,"current_make":false}
any help would be very greatful.
Just like to say code was supplied by BDMW.
Where you use the method array_keys(), instead of:
$return_array['makes'] = array_keys($vehicles_makes_models[$vehicle]);
Try this:
$return_array['makes'] = ! empty($vehicles_makes_models[$vehicle]) ? array_keys($vehicles_makes_models[$vehicle]) : [];
From what I've read, the array_keys() has been an issue depending on php versions. Hope this helps!

Load Template-Part with Ajax in Wordpress

Hi I am trying to add a feature to my store that when someone clicks on a product instead of being redirected to the product page, the product page loads with ajax in the home page like in this website (click on one of the products): http://www.itsjustyes.com. This is my jquery:
jQuery(document).ready(function($){
$('.info_btn').on('click',function(){
var theId = $(this).attr('id');
var div = $('#product-container')
$.post('wp-admin/admin-ajax.php',{
action:'my_get_posts',post_id: theId
}, function(data){
console.log(data);
div.html(data);
})
return false;
});
});
This is my code in functions.php:
//Ajax call to product
function my_get_posts_return()
{
global $post;
$post_id = intval(isset($_POST['post_id']) ? $_POST['post_id'] : 0);
if ($post_id > 0) {
$the_query = new WP_query(array('p' => $post_id));
if ($the_query->have_posts()) {
while ($the_query->have_posts()) : $the_query->the_post();
wc_get_template_part( 'content', 'single-product' );
endwhile;
} else {
echo "There were no posts found";
}
}
wp_die();
}
add_action('wp_ajax_my_get_posts', 'my_get_posts_return');
add_action('wp_ajax_nopriv_my_get_posts', 'my_get_posts_return');
I keep getting that there were no posts found in the loop which is weird cause I know I am sending the right post id. By the way, if I try to get the individual parts of the product page with get_the_title( $post_id ) I get it just fine. It's only when I try to load the template part with the loop that I get this problem. Any idea what I am doing wrong??
Your WP_Query was not finding the correct post type.
$the_query = new WP_query(array('p' => $post_id));
The query above didn't return any post at all. By default, wordpress will assume that you're querying the post_type = 'posts' which is why you cannot find the product post.
Therefore, you need to specify what post_type you're looking for. With WooCommerce product, you can use:
$the_query = new WP_query(array('p' => $post_id, 'post_type' => 'product'));
P.S. It's a good practice to use wp_localize_script function to register your ajaxurl, rather than hard coded in your javascript. You can follow this post for more detail.
Hope this helps.

Best method for firing and refiring AJAX via php

I'm trying to transcribe what my programmer told me. He and I may be doing this all wrong, so I need to make sure he and I am doing it in the right manner. Here is what we are trying to do:
I have a page on a website and within that page, I have a button. When you click on it, I want it to (via AJAX so the page doesn't refresh)
Send data (time capture) to the DB
See that the DB recorded the change and in turn return a different value back to the site
This would in turn change the button, noting that it is in a recording mode.
Think of it in this way, the button is a timer. On click, it records the time in the DB, and in the DB it also changes the state to recording. Since it is in the recording phase, somehow it gets sent back to the website page and changes the button showing that it is recording. Naturally clicking again would stop it and record the time in the DB.
Here is how the snippets are set up (not working I think) ATM:
*sidenote: This is in Joomla
Page:
<script src="js/ajax_link.js" type="text/javascript"></script>
<div id="ajaxlink" onclick="loadurl('php/ticket_timer.php',<?php echo $row->id?>)">Start Time</div>
ajax_link.js
function loadurl(dest,ticket_id) {
jQuery.ajax({
url: dest,
type: "POST",
data: "ticket_id="+ticket_id,
success: function(msg){
alert(msg);
jQuery('#ajaxlink').text("Timer Stop");
}
});
}
ticket_timer.php
<?php
define( '_JEXEC', 1 );
define( 'DS', DIRECTORY_SEPARATOR );
define( 'JPATH_BASE', $_SERVER[ 'DOCUMENT_ROOT' ] );
require_once( JPATH_BASE . DS . 'includes' . DS . 'defines.php' );
require_once( JPATH_BASE . DS . 'includes' . DS . 'framework.php' );
require_once( JPATH_BASE . DS . 'libraries' . DS . 'joomla' . DS . 'factory.php' );
$mainframe =& JFactory::getApplication('site');
$ticket_id = $_POST['ticket_id'];
$user =& JFactory::getUser();
$user_id=$user->get('id');
//DB Query
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('id', 'ticket_id', 'user_id', 'times','current_time')));
$query->from($db->quoteName('#__support_ticket_times'));
$query->where($db->quoteName('ticket_id') . ' LIKE '. $db->quote($ticket_id));
$query->where('ticket_id = '. $ticket_id, 'AND')
->where('user_id=' . $user_id );
$db->setQuery($query);
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();
$current_time=$results[0]->current_time;
$times=$results[0]->times;
$id_results = $db->loadColumn();
$db->setQuery($idquery);
$timesString = $times . ',' . date('Y-m-d g:i');
echo($timesString);
if(empty($results[0])){
$values = array(max($id_results)+1, $ticket_id, $user_id, $db->quote(date('Y-m-d g:i')),$db->quote(date('Y-m-d g:i')));
//echo "YOU GET NOTHING, MAKING NEW ROW";
$columns = array('id', 'ticket_id', 'user_id', 'times','current_time');
// Prepare the insert query.
$insert_query = $db->getQuery(true);
$insert_query
->insert($db->quoteName('#__support_ticket_times'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
// Set the query using our newly populated query object and execute it.
$db->setQuery($insert_query);
$db->query();
}else{
//echo("CURRENT TIME" . $current_time);
if($current_time=='0000-00-00 00:00:00'){
echo "NO TIME";
$fields = array(
$db->quoteName('current_time'). '=' . $db->quote(date('Y-m-d g:i'))
);
}
// . $db->quote(date('Y-m-d g:i'))
else{
echo "ADD TIME";
$fields = array($db->quoteName('times') . '=' . $db->quote($timesString) ,
$db->quoteName('current_time'). "='0000-00-00 00:00:00'"
);
}
$update_query = $db->getQuery(true);
$conditions = array(
$db->quoteName('user_id') . '=' . $db->quote($user_id),
$db->quoteName('ticket_id') . '=' . $db->quote($ticket_id)
);
$update_query->update($db->quoteName('#__support_ticket_times'))->set($fields)->where($conditions);
$db->setQuery($update_query);
$db->query();
//echo $update_query;
}
?>
Can anyone suggest how to get the timer to fire back that the timer has started? Are we butchering this and is there a better way to code this?
You need to exchange some data between the PHP and the HTML page. The HTML page can be modified with Javascript, of course. The notation typically used for this kind of an exchange is JSON. In this example, we're using JSON to:
Send a boolean timerRunning to the PHP,
change the value in PHP,
send a reply,
modify the HTML page, and
store the timerRunning value in the HTML element.
So, for starters, we pass some data from the HTML element to Javascript using the HTML5 data- attributes, like this:
<div id="ajaxlink" data-url="php/ticket_timer.php" data-ticketId="<?php echo $row->id; ?> " data-timerRunning="false">Start Time</div>
In your Javascript, we access the parameters set above and send them to your PHP script via AJAX:
jQuery(document).ready(function($){
// Add an 'onClick' handler to the element
jQuery('#ajaxlink').on('click', function(event) {
// Get the url and ticket_id from the element's 'data-' attributes
var url = jQuery(this).data( 'url' );
var data = {
'ticketId' : jQuery(this).data( 'ticketId' ),
'timerRunning' : jQuery(this).data( 'timerRunning' )
}
// Send an AJAX request
jQuery.ajax({
type: 'POST',
url: url,
data: data
}).done( function(response) {
// This runs when the AJAX request succeeds
if ( 'undefined' == typeof( response.timerRunning ) ) {
alert( 'The server didn\'t tell the timer state' );
return;
}
// Store the value in the element
jQuery('#ajaxlink').data( 'timerRunning', response.timerRunning );
// Change the element HTML
if ( response.timerRunning )
jQuery('#ajaxlink').html( 'Stop Timer' );
else
jQuery('#ajaxlink').html( 'Start Timer' );
}).fail( function(jqXHR, textStatus, errorThrown ) {
// This runs when the AJAX request fails
alert( 'The AJAX request failed with the error ' + errorThrown );
});
});
});
In your PHP script, check the timerRunning value and react accordingly:
if ( isset( $_POST['timerRunning'] ) ) { // Check that we got some value for 'timerRunning'
if ( $_POST['timerRunning'] ) {
// The 'timerRunning' value is TRUE, the timer is running, now stop it
your_code_here_to_stop_the_timer();
$reply = array( 'timerRunning' => false );
} else {
// The 'timerRunning' value is FALSE, the timer isn't running, now start it
your_code_here_to_start_the_timer_and_whatever();
$reply = array( 'timerRunning' => true );
}
// Send the correct header for a JSON response
header('Content-type: application/json');
// Send the $reply array encoded as JSON
echo json_encode( $reply );
}

Categories