I'm using wp_localize_script to send post data to ajax.
wp_localize_script( 'my-script.js', 'ajax_object', array('ajax_url' => admin_url('admin-ajax.php')) );
add_action( 'wp_ajax_load_more_posts', 'ajax_posts' );
Sending post data to ajax:
function ajax_posts(){
global $post;
$args = array('post_type'=>'post', 'posts_per_page'=> 2);
$posts_arr=[];
$query = new WP_Query($args);
if($query->have_posts()):
while($query->have_posts()):$query->the_post();
$posts_arr[] = $post;
endwhile;
wp_reset_postdata();
endif;
wp_send_json_success(array('post'=>$posts_arr));
}
In my ajax success function I'm using the following to append posts to the HTML:
success:function(response){
var post_data = response.data.post;
$.each(post_data, function(index, value) {
$("#content").append('' + value.post_title + '');
});
}
It adds 2 posts to the HTML. It works well but how can I also add the post url to the ajax_posts() php function and pass it to ajax and use?
This is the data I'm getting from ajax:
Is it possible to also add the post urls to the post arrays?
Note: I'm using ajax for loading more posts when clicking a button but simplified the code here. I cannot add php directly to the js. It must be sent from the ajax_posts() php function to ajax in my js.
You could simply do something like this:
function ajax_posts(){
global $post;
$args = array('post_type'=>'post', 'posts_per_page'=> 2);
$posts_arr=[];
$query = new WP_Query($args);
if($query->have_posts()):
while($query->have_posts()):$query->the_post();
$posts_arr[] = array(
'permalink' => get_permalink(),
'ID' => $post->ID,
'post_title' => $post->post_title,
'post_content' => $post->post_content,
'post_author' => $post->post_author,
'post_date' => $post->post_date
// Add more fields as needed here
);
endwhile;
wp_reset_postdata();
endif;
wp_send_json_success(array('post'=>$posts_arr));
}
Related
I am new to wordpress and I need to call a php function from ajax but my code is not working. I was reading about the ajax standard in wordpress, but I don't know what happens, I have followed several tutorials and answers in this blog and they all talk about the action to enqueue the javascript file, but the problem continues and I don't know what I'm doing wrong. To continue I share my code.
This is my function to enqueue my javascript file:
function enqueue_script() {
$ajax_script = 'popup';
$uri = get_stylesheet_directory_uri() . '/assets/front/js/popup.js';
wp_register_script($ajax_script, $uri);
wp_localize_script( $ajax_script, 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
wp_enqueue_script( $ajax_script, $uri, array('jquery'), rand(111,9999), 'all');
}
add_action( 'wp_enqueue_scripts', 'enqueue_script' );
My php function to call, this is in an update_request_status.php file:
function update_status(){
echo "<script>alert('I am update function!!!!');</script>";
}
This is my js action, :
$('.btn-confirm').click(function(){
var url_string = window.location.href;
var url = new URL(url_string);
var request_id = url.searchParams.get("request_id");
$.ajax({
url: ajax_object.ajaxurl,
type: 'POST',
cache: false,
data: { "request_id": request_id } + '&action=change_status',
success:function(data){
alert("YEs I doing");
},
error:function(){
alert("¡Error en el servidor, contancte al administrador!");
}
});
window.location.href = "http://localhost:8081/megafrescos/pendientes";
$('#msg-remove-request').css('display', 'none');
});
And finally, this is my modal with the button that triggers the action to call my php function:
<div class="warning-msg" id="msg-remove-request">
<button class="btn-close" id="btn-close">×</button>
<h5>¿Dar por concluida esta solicitud ? </h5><hr>
<?php echo fix_request()?>
<div class="confirm-btns">
<button class="btn-confirm">Aceptar</button>
<button class="btn-close">Cancelar</button>
</div>
<div class='update-status'></div>
</div>
Can somebody help me?
There are multiple ways to do it. First I'll show the one you were working on.
You'll need to define two actions with wp_ajax_{action} and wp_ajax_nopriv_{action}, where {action} is a placeholder for a keyword to identify the function that needs to be called. The former is only works when users are logged in. The latter is for request from unauthenticated users.
Both hooks should refer to the same function that you are trying to call.
The example below returns either the request_id that has been sent or a string with 'Nothing' as a response, just to test things out.
add_action( 'wp_ajax_nopriv_update_status', 'update_status' ) ;
add_action( 'wp_ajax_update_status', 'update_status' );
function update_status() {
$request_id = isset( $_POST[ 'request_id' ) ) ?
$_POST[ 'request_id' ) :
'Nothing';
echo $request_id;
}
The other, and more modern approach is using the REST API. This enables you to create an endpoint where you get more controls over de URL and sanitizing.
Your endpoint would look something like this
https://yourwebsite.com/wp-json/api/v1/update. You can get the static URL to the REST endpoint by using get_rest_url(), like you did with admin_url( 'admin-ajax.php' ) and should add that to your wp_localize_script function in the enqueue file.
The endpoint checks the methods allowed and calls the callback specified in the options array. From there you can access the $request object which contains info like the given arguments from your request.
Then return a response to read on the frontend.
add_action( 'rest_api_init', 'register_update_endpoint' );
function register_update_endpoint() {
// Register new route to get data from
register_rest_route( 'api/v1', // Mandatory prefix with version
'/update/', // Name of the route, can be anything.
array(
'methods' => array( 'POST' ), // Allowed methods.
'callback' => 'update_status' // Function to call when URL is called.
)
);
function update_status( WP_REST_Request $request ) {
$request_id = $request->has_param( 'request_id' ) ?
$request->get_param( 'request_id' ) :
'Nothing';
$response = new WP_REST_Response( $request_id; );
return $request_id;
}
}
-- Edit 1 --
Found out some new things. I'm adding them on top since they might be more relevant than the code below.
I've rerun the scripts a few times. I now get different findings actually.
Running var_dump($wp_query->query); right after $the_query = new WP_Query($queryArgs);In the first render of the post loop gives me the query vars of the page the loop is rendered on. Calling it with ajax it reruns the same part of the code, right? So than it returns empty.
My thoughts:
Pages is called, runs funtions.php.
Runs the part of the wp_enqueue_script('rtt_scripts');
This is the moment it gets the current $wp_query values. Which are the values of the page.
Than renders the page with the post loop.
This is the moment the post loop runs $the_query = new WP_Query($queryArgs);
On press of the load more the ajax than calls it to rerun the post loop. With the query vars set with wp_enqueue_script('rtt_scripts');
This made me think. Am I running the code in a wrong order? Are the query vars for ajax set on the wrong moment? Other thought. Should I focus on how to get the query vars on the first post loop to the ajax query vars?
-- End Edit --
I’m having trouble with a load more button in Wordpress. The code below is the basic code I have right now.
As far as I can see this should be a working code :) Problem is though that this doesn’t work.
My problem is that I don’t know where to start debugging. Closest I know where the problem lies is this:
In rtt_loadmore_ajax_handler() there is the var $queryArg
When var_dumping the var $queryArg in both rtt_post_grid() and rtt_loadmore_ajax_handler()
It gives different results. Here I would expect the same results. In the Ajax call it returns the arguments
of the current rendered page and not of the post query on this page.
Would the global $wp_query; be the problem? And how do I go from here?
The basic post code:
function rtt_post_grid()
{
$queryArgs = Array(
"post_type" => Array(
'news',
'agenda'
),
'posts_per_page' => 4,
'post_status' => 'publish',
'paged' => 1
);
// post grid wrap
echo '<div id="rtt_posts_wrap" >';
rtt_post_grid_query($queryArgs);
echo '</div>';
// load more button
echo '<form>';
echo '<button id="rtt_loadmore" class=" button">Load more post</button> ';
echo '<input type="hidden" name="action" value="loadmore" />'; // this line might be obsolete
echo '</form>';
}
function rtt_post_grid_query($queryArgs)
{
// The Query
$the_query = new WP_Query($queryArgs);
// The Loop
if ($the_query->have_posts()) {
echo '<ul>';
while ($the_query->have_posts()) {
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
/* Restore original Post Data */
wp_reset_postdata();
} else {
// no posts found
echo 'no posts found';
}
}
Setting the JS:
if(!has_action('rtt_post_grid_script_and_styles')) {
add_action('wp_enqueue_scripts', 'rtt_post_grid_script_and_styles', 1);
function rtt_post_grid_script_and_styles()
{
global $wp_query;
wp_register_script('rtt_scripts', plugin_dir_url( __FILE__ ) . 'js/script.js', array('jquery'), time());
wp_enqueue_script('rtt_scripts');
wp_localize_script('rtt_scripts', 'rtt_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode($wp_query->query_vars), // everything about your loop is here
'current_page' => $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1,
'max_page' => $wp_query->max_num_pages
));
wp_enqueue_script('rtt_scripts');
}
}
The JS/Ajax:
jQuery(function($){
$(window).ready(function() {
$('#rtt_loadmore').click(function () {
$.ajax({
url: rtt_loadmore_params.ajaxurl,
data: {
'action': 'loadmore', // the parameter for admin-ajax.php
'query': rtt_loadmore_params.posts, // loop parameters passed by wp_localize_script()
'page': rtt_loadmore_params.current_page, // current page
},
dataType: 'json',
type: 'POST',
beforeSend: function (xhr) {
$('#rtt_loadmore').text('Bezig met laden...'); // some type of preloader
},
success: function (data) {
if (data) {
$('#rtt_loadmore').text('More posts');
$('#rtt_posts_wrap').append(data.content); // insert new posts
rtt_loadmore_params.current_page++;
if (rtt_loadmore_params.current_page == rtt_loadmore_params.max_page){
$('#rtt_loadmore').hide(); // if last page, HIDE the button
}
} else {
$('#rtt_loadmore').hide(); // if no data, HIDE the button as well
}
}
});
return false;
});
});
});
The Ajax handler:
add_action('wp_ajax_loadmore', 'rtt_loadmore_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'rtt_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}
function rtt_loadmore_ajax_handler(){
$postData = $_POST;
// prepare our arguments for the query
$queryArgs = json_decode( stripslashes( $postData['query'] ), true );
$queryArgs['paged'] = $postData['page'] + 1; // we need next page to be loaded
$queryArgs['post_status'] = 'publish';
ob_start();
rtt_post_grid_query($queryArgs);
$output = ob_get_contents();
ob_end_clean();
global $the_query;
echo json_encode( array(
'posts' => serialize( $the_query->query_vars ),
'max_page' => $the_query->max_num_pages,
'found_posts' => $the_query->found_posts,
'content' => $output
) );
die;
}
So, I've figured it out. I'll explain for it might be useful to somebody else.
The reason it did not work is because the code above is more useful in a template. But I use it in a shortcode. The wp_localize_script() was run on rendering the page and not on running the shortcode. That's why it didn't had the right variables.
I've moved the code below inside the shortcode. Right after the new WP_query:
// The Query
$the_query = new WP_Query($queryArgs);
// The Loop
if ($the_query->have_posts()) {
wp_enqueue_script_ajax_vars($the_query);
Than passed the new query
function wp_enqueue_script_ajax_vars($the_query)
{
wp_register_script('rtt_scripts', plugin_dir_url(__FILE__) . 'js/script.js', array('jquery'), time());
wp_localize_script('rtt_scripts', 'rtt_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode($the_query->query_vars), // everything about your loop is here
'query_vars' => json_encode($the_query->query),
'current_page' => $the_query->query_vars['paged'] ? $the_query->query_vars['paged'] : 1,
'max_page' => $the_query->max_num_pages,
));
wp_enqueue_script('rtt_scripts', '', '', '', true); // note the last 'true' this sets it inside the footer
}
Resulting in wp_localize_script() creating the variable in the footer. It was in the header before. But by getting it within the shortcode, sending the new query arguments and putting them inside the footer (since the header is already rendered by then) I have set the JS var for Ajax.
Add the two order arguments to $queryArgs.
// prepare our arguments for the query
$queryArgs = json_decode( stripslashes( $postData['query'] ), true );
$queryArgs['paged'] = $postData['page'] + 1; // we need next page to be loaded
$queryArgs['post_status'] = 'publish';
$queryArgs['orderby'] = 'date'; // add this to order by date
$queryArgs['order'] = 'DESC'; // add this to display the most recent
I have a PHP code that creates a JSON data from wordpress posts in the database.
I load this JSON on my html page using AJAX.
The above works fine.
Now I need to add a "Load More" button so everytime its pressed, we load another 10 posts and append/add them to the ones that were already loaded WITHOUT having to delete the old ones and re-adding them.
So this my AJAX code for loading more:
var i = 0;
$(document).on("click", ".loadMoreBtn", function () {
$.ajax({
url: 'https://some-domain.com/index.php?t=' + mainCat + '&page=' + i + '',
dataType: 'json',
jsonp: 'jsoncallback',
timeout: 5000,
success: function (data, status) {
if (!$.trim(data)) {
}
else {
}
$.each(data, function (pi, item) {
var id = item.id;
var img = item.img;
var title = item.title;
var date_added = item.date_added;
var item = '' + title + '';
$('.myDiv').before(item);
i++;
});
},
error: function () {
//error handling////
}
});
});
And this is my PHP code:
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
$path = $_SERVER['DOCUMENT_ROOT'];
include_once $path . '/wp-config.php';
include_once $path . '/wp-load.php';
include_once $path . '/wp-includes/wp-db.php';
include_once $path . '/wp-includes/pluggable.php';
$t = $_GET['t'];
$page = $_GET['page'];
$posts = get_posts(array(
'posts_per_page' => $page, //add -1 if you want to show all posts
'post_type' => 'post',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $t //pass your term name here
)
))
);
$output= array();
foreach( $posts as $post ) {
$feat_image = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
$mysqldate = $post->post_date;
$phpdate = strtotime( $mysqldate );
$mysqldate = date( 'F d Y', $phpdate );
// Pluck the id and title attributes
$output[] = array( 'id' => $post->ID, 'title' => $post->post_title, 'date_added' => $mysqldate, 'img' =>$feat_image );
}
echo json_encode( $output );
When I click on the 'Load More' button, it acts strangely! it basiclaly adds the old data and multiplies the same ones and adds/loads some new ones as well.
I know I am missing something in my PHP code but I couldn't figure out what.
Could someone please advice on this issue?
Thanks in advance.
The error is in your wordpress query. "posts_per_page" set how many posts will be loaded. Set that as how many post should be loaded like 12 or something.
The parameter your want to set as your $page parameter is "paged".
Eg. $query = new WP_Query( array( 'paged' => 6 ) ); // page number 6
https://codex.wordpress.org/Class_Reference/WP_Query#Pagination_Parameters
You could also use WP API instead of rolling your own
On my wordpress page, I have the following loop, which successfully outputs an attachment's caption.
<?php
$the_query = new WP_Query(array( 'post_type' => 'attachment'));
while ( $the_query->have_posts() ) : $the_query->the_post();
$attachment_data = wp_prepare_attachment_for_js();
echo '<h2>'.$attachment_data['caption'].'</h2>'
;?>
Now, I also need to call the attachment caption outside of the loop. This is what I'm trying in functions.php:
function custom_info()
{
global $wp_query;
$query_id = $wp_query->post->ID;
$attachment_data_query = wp_prepare_attachment_for_js( $query_id );
wp_register_script( 'custom_data_info');
$info = array(
'data_query' => $attachment_data_query['caption']
);
wp_enqueue_script( 'custom_data_info' );
wp_localize_script('custom_data_info', 'info', $info);
}
if ( !is_admin() ) add_action( "wp_enqueue_scripts", "custom_info", 10 );
And then it would be called in the external javascript file like so:
return info.data_query
I know the custom_info function and javascript file are talking with each other correctly. The problem is with how I am defining $query_id
EDIT: Almost fixed. The problem was that I didn't include a foreach statement, and so the first item in the loop was being repeated over and over again.
I've adjusted below, but for some reason, now the array is empty upon output of info.data_query...
function custom_info(){
global $wp_query;
wp_register_script( 'custom_data_info');
$info = array('data_query' => array());
foreach ( $wp_query->posts as $query_id) {
$attachment_data_query = wp_prepare_attachment_for_js( $query_id );
$info['data_query'][$query_id] = $attachment_data_query['caption'];
}
Are you sure $wp_query will return the correct post ID? In my experience, it's better to use global $post instead. Pass that into wp_prepare_attachment_js() instead:
global $post;
$post_id = $post->ID;
$attachment_data_query = wp_prepare_attachment_for_js( $post_id );
I have really weird problem with AJAX.
This is fragment of file with js code and post method which sends params to php file via AJAX:
var params = $('#add').serializeArray();
$.post('code/bg/adding_c.php', params, function(ret) {
//body of success function
}, 'json');
And this is fragment of php code (adding_c.php):
<?php
require "functions.php";
//irrelevant operations
$return = array(
'status' => $status,
'msg' => $msg,
'id' => $id
);
echo json_encode($return);
?>
Everything works when I comment or delete the line with require instruction but when it's active, success function isn't fired.
JS post method sends correct params.
Php file receives it, does proper operations and returns correct data to js script (I can see it in FireBug).
Success function isn't fired.
Why instruction which isn't related with AJAX, causes this problem?
Edit.
functions.php:
<?php
$host = 'localhost';
$user = 'root';
$pass = '';
$db = 'dbname';
$conn = new mysqli($host, $user, $pass, $db);
function querySQL($query)
{
global $conn;
$result = $conn->query($query);
return $result;
}
function cleanSQL($conn, $string)
{
return htmlentities(fixSQL($conn, $string), ENT_COMPAT, 'UTF-8');
}
function fixSQL($conn, $string)
{
if(get_magic_quotes_gpc())
$string = stripslashes($string);
return $conn->real_escape_string($string);
}
function fPassword($pass)
{
$salt1 = 'salt1';
$salt2 = 'salt2';
$token = hash('ripemd128', "$salt1$pass$salt2");
return $token;
}
?>
Edit2.
There is no errors and when I paste functions from functions.php to index.php everything works fine. I don't know what to do now. It seems that require word is a problem here. I can't add these functions to every file in which I need them.
It is probably an error within functions.php.
EDIT: If you haven't set display_errors = On in your php.ini file, use these lines in your code:
ini_set("display_errors", "1");
error_reporting(E_ALL);
Also, are you sure it is not a parsing/syntax error? If that is the case, there's a few things you will want to do:
Make sure you are using an IDE that checks syntax (Netbeans, for example).
Separate the file into two, like so:
index.php
<?php
ini_set("display_errors", "1");
error_reporting(E_ALL);
include 'error.php';
error.php
require "functions.php";
//irrelevant operations
$return = array(
'status' => $status,
'msg' => $msg,
'id' => $id
);
echo json_encode($return);
Run this in a browser window and that should give you an idea of what you are dealing with.