I am building a news blog that upload posts every hour. I have created a shortcode that displays the last 15 posts on the home page. My problem was that the server cache needed to be deleted every hour. so I've decided to serve the post via AJAX so this area will get the latest posts every page load.
I found this answer and combine it whit my code.
My problem is that it displays all of the posts and not just 15.
PHP:
function get_ajax_posts() {
// Query Arguments
$args = array(
'post_type' => array('post'),
'post_status' => array('publish'),
'posts_per_page' => 15,
'nopaging' => true,
'order' => 'DESC',
'orderby' => 'date',
);
$ajaxposts = new WP_Query( $args );
$response = '';
if ( $ajaxposts->have_posts() ) {
while ( $ajaxposts->have_posts() ) {
$ajaxposts->the_post();
$response .= get_template_part( 'template-parts/content-archive');
}
} else {
$response .= get_template_part('none');
}
echo $response;
exit; // leave ajax call
}
// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_ajax_posts');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_ajax_posts');
JS:
$.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php');?>',
dataType: "html",
data: { action : 'get_ajax_posts' },
success: function( response ) {
$( '.home-hot-flights' ).html( response );
//hot-flights
var hot_flights_item = $(".home-hot-flights article").width() + 17;
$(".art-move-left").click(function () {
$('.move-right').addClass('show-move-right');
var leftPos = $('.home-hot-flights').scrollLeft();
$(".home-hot-flights").animate({scrollLeft: leftPos - hot_flights_item}, 200);
});
$(".art-move-right").click(function () {
var leftPos = $('.home-hot-flights').scrollLeft();
$(".home-hot-flights").animate({scrollLeft: leftPos + hot_flights_item}, 200);
});
}
});
This might help you:
Pagination parameters
(nopaging (boolean) – show all posts or use pagination. Default value
is ‘false’, use paging. )
Display all posts by disabling pagination:
$query = new WP_Query( array( 'nopaging' => true ) );
I think you should remove that parameter if you want to display a certain number of posts using posts_per_page.
Try this piece of code I have edit your code please see below
function get_ajax_posts() {
// Query Arguments
$args = array(
'post_type' => array('post'),
'post_status' => array('publish'),
'posts_per_page' => 15,
'order' => 'DESC',
'orderby' => 'date',
);
wp_reset_query();
$ajaxposts = new WP_Query( $args );
$response = '';
if ( $ajaxposts->have_posts() ) {
while ( $ajaxposts->have_posts() ) {
$ajaxposts->the_post();
$response .= get_template_part( 'template-parts/content-archive');
}
} else {
$response .= get_template_part('none');
}
echo $response;
exit; // leave ajax call
}
// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_ajax_posts');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_ajax_posts');
If the two loops data is overwridden then, I your first code wp_reset_query() is incorrect. If you are using WP_Query then
wp_reset_postdata() //remove wp_reset_query() which is used for wp_query()
should be used after the end of the WHILE loop which means that in your two loops you have to have
wp_reset_postdata() // use this at both loops
Related
I have code to get some data (terms = page-a) built with Wordpress.
Currently, the data of page-a is acquired like'terms' =>'page-a' and displayed on the example.com/page-a page.
I would like to change this data acquisition code so that the data along the lower page url can be acquired (for example, the data on page-b at example.com/page-b).
I created a code to get the url with $_SERVER and convert it, but I can't get the url because I am using ajax. I want to get the url with javascript and pass it to php.
How should I make the changes?
functions.php
add_action('wp_ajax_get_case', 'dk_get_case');
add_action('wp_ajax_nopriv_get_case', 'dk_get_case');
function dk_get_case() {
$headers['Access-Control-Allow-Origin'] = '*';
$return = ['status' => false, 'data' => [], 'message' => ''];
$case_clinics = [1,2,3,4];
foreach($case_clinics as $key => $case_clinic){
// (1)Get the current URL
$http = is_ssl() ? 'https' : 'http' . '://';
$url = $http . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
// (2)Get a string such as'page-a' from the URL
$keys = parse_url($url);
$path = explode("/", $keys['path']);
$terms = $path[2];
$dk_posts = get_posts(
array(
'showposts' => -1,
'post_type' => 'case',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'case_clinic',
'field' => 'term_id',
'terms' => $case_clinic
),
array(
'taxonomy' => 'case_category',
'field' => 'slug',
'terms' => 'page-a'
)
)
)
);
taxonomy-case_category-page-a.php
<div class="col case-right">
<h3 style="font-family:'Futura PT'; font-weight:600">Clinic</h3>
<h4 style="font-weight:600">Clinic</h4>
//data display position
<div class="case-img" data-slider-3></div>
<div class="popup"></div>
</div>
Tried
footer.php
<script>
jQuery(document).ready(function () {
var url = window.location.href;
$.ajax({
type: "GET",
url: "taxonomy-case_category-page-a.php",
data: {"url": url},
});
});
taxonomy-case_category-page-a.php
<?php var_dump($_GET['url']); ?>
error
GET: 404error
https://example.com/pagea/taxonomy-case_category-page-a.php?url=https%3A%2F%2Fcharme-beauty.jp%2Fstaging%2Fcase%2Fpagea%2F
Im having trouble trying to call my function in my Function.php this is the function
enqueue script & localize
function my_enqueue() {
wp_enqueue_script( 'wc_shop', get_template_directory_uri() . '/wc_shop.js', array('') );
wp_localize_script( 'wc_shop', 'a_product_filter',
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}
add_action( 'wp_enqueue_scripts', 'my_enqueue' );
the Function thats in function.php that im trying to call that filters product
add_action('wp_ajax_a_product_filter', 'a_product_filter');
add_action('wp_ajax_nopriv_a_product_filter', 'a_product_filter');
function a_product_filter() {
echo "called";
$args = array(
'post_type' => 'product',
'posts_per_page' => 5,
'product_tag' => 'FEMALE' //just for testing without passing a variable
);
// Create the new query
$loop = new WP_Query( $args );
// Get products number
$product_count = $loop->post_count;
// If results
if( $product_count > 0 ) :
echo '<ul class="products">';
// Start the loop
while ( $loop->have_posts() ) : $loop->the_post(); //global $product;
//global $post;
wc_get_template_part( 'content', 'product' );
echo ''.get_the_title($product_id).'';
if (has_post_thumbnail( $loop->post->ID ))
echo get_the_post_thumbnail($loop->post->ID, 'shop_catalog');
else
echo '<img src="'.$woocommerce .'/assets/images/placeholder.png" alt="" width="'.$woocommerce->get_image_size('shop_catalog_image_width').'px" height="'.$woocommerce->get_image_size('shop_catalog_image_height').'px" />';
endwhile;
echo '</ul><!--/.products-->';
else :
_e('No product matching your criteria.');
endif; // endif $product_count > 0
}
this is the call I'm calling from the front end i cant even get the a_product_filter to echo 'called'
function ajax_call_test(){
// data to be sent to the POST request
let _data = {
action : 'a_product_filter',
}
fetch(a_product_filter.ajax_url , {
method: "POST",
body: JSON.stringify(_data),
headers: {"Content-type": "application/json; charset=UTF-8"}
})
.then(response => response.json())
.then(json => console.log(json));
}
I keep getting 400 Bad Request can someone help me and tell me what is wrong with this
Just like what I have stated in the comments, the backend requires you to send a request in normal POST fashion, not in JSON.
So use application/x-www-form-urlencoded as your header and send query string in the body, not JSON.
let _data = { action : 'a_product_filter', product_something: 'value that i want to send to the server'};
fetch(a_product_filter.ajax_url, {
method: 'POST',
body: (new URLSearchParams(_data)).toString(),
headers: { 'Content-type': 'application/x-www-form-urlencoded' }
})
.then(response => response.text())
.then(product_html => document.getElementById('container').insertAdjacentHTML(product_html));
// put the markup created by server and put it inside somewhere in the frontend
Then on the backend, prepare for that request. Here's an untested code that you can use in the server. So that when the front end requests it, your server (the PHP code that will handle the request will give out the markup with the product you want to respond).
Just follow this idea. Create the markup and respond (echo and exit).
add_action('wp_ajax_a_product_filter', 'a_product_filter');
add_action('wp_ajax_nopriv_a_product_filter', 'a_product_filter');
function a_product_filter() {
// $variable = $_POST['product_something'];
$html_markup = _e('No product matching your criteria.');
$args = array(
'post_type' => 'product',
'posts_per_page' => 5,
'product_tag' => 'FEMALE' //just for testing without passing a variable
);
$loop = new WP_Query($args);
if ($loop->found_posts > 0) {
// get template in string
ob_start();
wc_get_template_part('content', 'product');
$template = ob_get_contents();
ob_end_clean();
$html_markup = '<ul class="products">';
foreach ($loop->get_posts() as $post) {
$html_markup .= '<li>'; // initialize list item
$html_markup .= $template; // add the template
$html_markup .= '' . get_title($post->ID). ''; // link and title
$html_markup .= has_post_thumbnail( $loop->post->ID) ? get_the_post_thumbnail($post->ID, 'shop_catalog'); : '<img src="placeholder.jpg" />' ; // image of product
$html_markup .= '</li>'; // end list item
}
$html_markup .= '</ul>';
}
echo $html_markup;
exit;
}
I am using ajax to send data to a custom rest endpoint. I am doing this because i'm creating a filter function on my WP site.
Now I am stuck trying to get the tax_query to work with my array of terms collected with JS on the front end. No matter what I do I cant seem to get this to work, and I am strongly suspecting this is only a minor error that I keep overlooking...
Just to clarify, the ajax sends the request successfully but the query returns all posts no matter what.
Here is the checkboxes used on the front end:
<div class="form-group">
<?php
if( $terms = get_terms( array( 'taxonomy' => 'utst', 'hide_empty' => false, 'orderby' => 'name' ) ) ) :
foreach ( $terms as $term ) :
echo '<div class="form-check">';
echo '<label class="form-check-label" for="'.$term->slug.'"><input class="form-check-input" type="checkbox" id="'.$term->slug.'" name="utstyrAr[]" value="'.$term->term_id.'"> '.$term->name.'</label>'; // ID of the category as the value of an option
echo '</div>';
endforeach;
endif;
?>
</div>
The JS (ajax function):
filterOppdrag(fiOppdrag) {
var utst = [];
var utstyrArray = document.getElementsByName("utstyrAr[]");
for (var i = 0; i < utstyrArray.length; i++) {
if(utstyrArray[i].type =='checkbox' && utstyrArray[i].checked == true) utst.push(utstyrArray[i].value);
}
console.log(utst);
$.ajax({
url: the.root + '/wp-json/myfilter/v1/filter',
type: 'GET',
data: {
'checkUtst' : utst,
},
success: (response) => {
console.log(response);
},
error: (response) => {
console.log(response);
}
});
}
And the wp_query (php):
function myFilter ($data) {
$checkUtst = sanitize_text_field($data['checkUtst']);
//Main $args
$args = array(
'post_type' => 'ml_opp', // Query only "ml_opp" custom posts
'post_status' => 'publish', // Query only posts with publish status
'orderby' => 'date', // Sort posts by date
'order' => 'ASC' // ASC or DESC
);
// for taxonomies / utstyr
if( isset( $utstyr ) )
$args['tax_query'] = array(
array(
'taxonomy' => 'ml_utst',
'field' => 'id',
'terms' => $checkUtst
)
);
$query = new WP_Query( $args );
if( $query->have_posts() ) :
while( $query->have_posts() ): $query->the_post();
echo '<h2>' . $query->post->post_title . '</h2>';
endwhile;
wp_reset_postdata();
else :
echo 'No posts found';
endif;
die();
}
This returns all the posts regardless of terms no matter what I pass through. I get no error messages and yes I have tested so that there is value in the array when I send it to the query. But what happens to it on the road there, I dont know. That's why i figure that Its probably just a rookie mistake I am making here.
Any help would be greatly appreciated!
Have you tried removing the wrapping array and not using a key?
$args = array(
'taxonomy' => 'ml_utst',
'field' => 'id',
'terms' => $checkUtst
);
I am trying to add a fee to checkout based on whether or not a custom checkbox I've added it checked. I am really close to getting this to work, but I'm having issues getting the post values to determine if the fee should be applied or not.
Here is the code I have for my custom field:
add_action( 'woocommerce_after_checkout_billing_form', 'my_custom_fields' );
function my_custom_fields( $checkout ) {
echo '<div id="message_fields"><h3>' . __('Add a Message') . '</h3>';
woocommerce_form_field( 'add_gift_message', array(
'type' => 'checkbox',
'class' => array('gift_message form-row-wide'),
'label' => __('5x7 Enclosed Personal Message - $4'),
'placeholder' => __(''),
), $checkout->get_value( 'add_gift_message' ));
woocommerce_form_field( 'gift_message', array(
'type' => 'textarea',
'class' => array('gift_message_text form-row-wide'),
'label' => false,
'placeholder' => __('Your message'),
), $checkout->get_value( 'gift_message' ));
echo '</div>';
}
This works, and the fields show up perfectly.
At the bottom of form-checkout.php in my theme, I have added this javascript to update the cart total when the field it checked:
<script type="text/javascript">
jQuery( document ).ready(function( $ ) {
$('#add_gift_message').click(function(){
if ( $(this).is(':checked') ) {
$('#gift_message_field').show();
var gift_message= true;
} else {
$('#gift_message_field').hide();
var gift_message = false;
}
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: $( 'form.checkout' ).serialize(),
success: function( response ) {
if ( response ) {
var order_output = $(response);
$( '#order_review' ).html( $.trim( order_output ) );
$('body').trigger('update_checkout');
}
},
error: function(code){
},
dataType: 'html'
});
});
});
</script>
This updates the order total and runs the following code (this is where the problem is):
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
function woo_add_cart_fee( $data ){
global $woocommerce;
if ( isset($_POST['add_gift_message']) )
$woocommerce->cart->add_fee( 'Personal Gift Message', '4.00', true, 'standard' );
}
I know this part is being called because if I take out if ( isset($_POST['add_gift_message']) ), it adds the fee. What I'm having trouble with is determining if the field has been checked or not - I can't seem to get the POST values inside of woo_add_cart_fee no matter what I do.
Does anyone know how to get this to work? Thank you!!
The reason why you unable to get value from $_POST['add_gift_message'] is because update_checkout is an ajax event and it serialise form data into $_POST['post_data']. So, in order to cater for getting the value before (ajax) and during(non-ajax) user check out, you can get that by using below code:
if ( isset( $_POST['post_data'] ) ) {
parse_str( $_POST['post_data'], $post_data );
} else {
$post_data = $_POST; // fallback for final checkout (non-ajax)
}
if ( isset( $post_data['add_gift_message'] ) ) {
$woocommerce->cart->add_fee( 'Personal Gift Message', '4.00', true, 'standard' );
}
for reference, can see this post
I have an item with the following data :
var item = {
id : "124",
name : "xxx",
price : "13.13",
quantity : 1,
options : {
"size" : "xl",
"color": "pink"
}
};
When the user clicks on "Add to Cart" I'd like to make an Ajax Request using the WC API and add the above item to the Cart.
jQuery.ajax({
url: "some/woocommerce/api/add/to/cart/request/path",
data: item,
type: "POST"
});
Then on the Cart Page I'd like to make another Ajax Request using the WC API and retrieve the contents of the cart.
I haven't found any documentation (official or unofficial) on how to do that from the client using Javascript.
Does anyone know and can provide me with an example please?
Also, does anyone know why the WooCommerce Api Documentation is so horrible (lacking any kind of information regarding obvious/standard questions like the above). I'm seriously thinking of having our company switch to Shopify.
You can investigate how WooCommerce is adding items to the cart via ajax directly in the code.... the callback is located in includes/class-wc-ajax.php. WooCommerce already does this on product "loops" (product archives), so I don't think you need to reinvent the wheel and if their existing code doesn't work for what you are trying to do, then you should be able to borrow heavily from it.
The beginning of that file has a loop with all the WooCommerce Ajax actions, but we can track down that the add to cart is basically this:
add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart', array( 'WC_AJAX', 'add_to_cart' ) );
And it's callback is a little further down the file:
/**
* AJAX add to cart
*/
public static function add_to_cart() {
ob_start();
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
$quantity = empty( $_POST['quantity'] ) ? 1 : wc_stock_amount( $_POST['quantity'] );
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data );
if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity ) ) {
do_action( 'woocommerce_ajax_added_to_cart', $product_id );
if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) {
wc_add_to_cart_message( $product_id );
}
// Return fragments
self::get_refreshed_fragments();
} else {
// If there was an error adding to the cart, redirect to the product page to show any errors
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id )
);
wp_send_json( $data );
}
die();
}
If you want to view their add to cart ajax call, the JS for that is located in assest/js/frontend/add-to-cart.js.
EDIT
Now that I know you are looking to add a variation, maybe we can tweak the above.
First, I think you'll need to pass the AJAX url to your script:
wp_enqueue_script( 'wc-variation-add-to-cart', 'source-to-script/your-script.js' );
$vars = array( 'ajax_url' => admin_url( 'admin-ajax.php' ) );
wp_localize_script( 'wc-variation-add-to-cart', 'WC_VARIATION_ADD_TO_CART', $vars );
Then your AJAX call would look something like this:
jQuery.ajax({
url: WC_VARIATION_ADD_TO_CART.ajax_url,
data: {
"action" : "woocommerce_add_variation_to_cart",
"product_id" : "124",
"variation_id" : "125",
"quantity" : 1,
"variation" : {
"size" : "xl",
"color": "pink"
},
},
type: "POST"
});
Basically to add a specific variation you need the variation's ID in addition to all its specific options.
And finally the new callback for the woocommerce_add_variation_to_cart ajax action would be along the lines of the following:
add_action( 'wp_ajax_nopriv_woocommerce_add_variation_to_cart', 'so_27270880_add_variation_to_cart' );
function so_27270880_add_variation_to_cart() {
ob_start();
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
$quantity = empty( $_POST['quantity'] ) ? 1 : wc_stock_amount( $_POST['quantity'] );
$variation_id = isset( $_POST['variation_id'] ) ? absint( $_POST['variation_id'] ) : '';
$variations = ! empty( $_POST['variation'] ) ? (array) $_POST['variation'] : '';
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data );
if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) ) {
do_action( 'woocommerce_ajax_added_to_cart', $product_id );
if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) {
wc_add_to_cart_message( $product_id );
}
// Return fragments
WC_AJAX::get_refreshed_fragments();
} else {
// If there was an error adding to the cart, redirect to the product page to show any errors
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id )
);
wp_send_json( $data );
}
die();
}
Mostly, I'm just copying WooCommerce's approach and adding in the 2 variables needed for adding variations. Totally untested, but I hope it helps.
If anyone is interested I've also written a "remove from cart" function to counter the add to cart. My project called for radio buttons on checkout so I needed to add a product and remove the alternative it was already there:
Here's the php:
function remove_from_cart( $product_id ) {
$cart_contents = WC()->cart->get_cart();
if (empty($product_id)) { $product_id = $_POST['product_id']; }
foreach ($cart_contents as $product_key => $product){
if ($product['variation_id'] == $product_id){
WC()->cart->remove_cart_item($product_key);
}
}
}
add_action( 'wp_ajax_nopriv_remove_from_cart', 'remove_from_cart' );
And then here's the jQuery:
function remove_item_from_cart(product){
var data = {
"action" : "remove_from_cart",
"product_id" : product,
};
jQuery.post(WC_VARIATION_ADD_TO_CART.ajax_url, data, function(response) {
$(document.body).trigger("update_checkout");
});
}
The if(empty)... in the php was so I could call the function from the server side as well if I needed to.