Call any Wordpress PHP function via AJAX [duplicate] - php

This question already has an answer here:
Calling PHP function from wordpress in ajax?
(1 answer)
Closed 5 years ago.
It's very difficult for me to learn the basics of AJAX since I was managed to find only complicated examples. In fact, I want to do an apparently simple thing, but I wasn't able to find any easy solution. There are numerous instructions how to use AJAX to check various forms, etc. But there is few data how this technology work in WordPress.
The official instruction was useless to me as well:
https://codex.wordpress.org/AJAX_in_Plugins
What exactly I need?
For example, I have some function in functions.php. Let it be a just simple string:
<?php
function do_echo() {
echo "Hello";
}
Now, I want to create a button inside my post and call do_echo() using AJAX.
<button class="my_button" type="button" role="button">Click Me</button>
So, the first and foremost thing I want to do is just push on the button and get "Hello, world!" displayed.
Of course, in fact, I need to execute the more complicated function. But, first of all, I need to do these simple things.
I realize that I need to do something like this using jQuery
$.ajax({
url: '/path/to/file',
type: 'default GET (Other values: POST)',
dataType: 'default: Intelligent Guess (Other values: xml, json, script,
or html)',
data: {param1: 'value1'},
})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
I understand that I need to do something like this in PHP
add_action('wp_ajax_(action)', 'my_action_callback');
add_action('wp_ajax_nopriv_(action)', 'my_action_callback');
But I can't understand what exact steps I need to do to attach these things to WordPress.
Can anyone assist me with the simple instruction how to call any PHP function from functions.php in WordPress using AJAX when the button was clicked?
Thank you in advance.

Okay, let's write simplified example for this.
Here is a sample for functions.php:
add_action('wp_ajax_nopriv_sayhello', 'say_hello_function');
add_action('wp_ajax_sayhello', 'say_hello_function');
function say_hello_function(){
echo 'hello';
exit();
}
And this is front-end part:
<button class="my_button" type="button" role="button">Click Me</button>
<script>
jQuery(".my_button").click(function(){
jQuery.get(ajaxurl,{'action': 'sayhello'},
function (msg) { alert(msg);});
});
</script>
UPD:
To display returned data in your website content:
<script>
jQuery(".my_button").click(function(){
jQuery.get(ajaxurl,{'action': 'sayhello'},
function (msg) { jQuery(".result_area").html(msg);});
});
</script>
To get above code working you need to have a div with "result_area" class.
<div class="result_area"></div>

The best pratice is using WP Rest API
Wordpress provide an simple and organized way to add API Routes that return JSON.
You can register your routes in function.php or another loaded file.
Major WP files will be loaded and you can use your functions.
WP example:
<?php
/**
* Grab latest post title by an author!
*/
function my_awesome_func( $data ) {
$posts = get_posts( array(
"author" => $data["id"],
) );
if ( empty( $posts ) ) {
return null;
}
return $posts[0]->post_title;
}
add_action( "rest_api_init", function () {
register_rest_route( "myplugin/v1", "/author/(?P<id>\d+)", array(
"methods" => "GET",
"callback" => "my_awesome_func",
) );
} );

Related

How to run CookieList (MODx extension) with ajax

Please, explain to me how to run snippet CookieList with ajax?
I tried next:
1. Created snippet ajaxCookieList:
<?php
if (isset($_POST["action"])) {
$values = $modx->runSnippet('addToCookieLIst',array(
'value' => $_POST['action']
));
$output = $modx->runSnippet('pdoResources',[
'parents' => 6,
'resources' => $values,
'tpl' => 'popup.favorites.item',
'includeTVs' => 'header.bgImage,franchise.logo,franchise.price,title,subtitle',
'prepareTVs' => '1',
'hideContainers' => '1'
]);
return $output;
}
Then i created chunk with this code:
<script>
jQuery(function($){
$('a.franchise-pin, a.franchise-favorite-add').click(function(e){
var value = $(this).data('value');
$.post(document.location.href, {action: value}, function(data) {
$('#favorites').html(data);
$('#favorites').modal('show');
});
e.preventDefault();
});
});
</script>
But response is all page..
What is wrong?
What I usually do in such cases:
I place a snippet call ([[!ajaxCookieList]]) on a service page
accessible via URL like /page-with-snippet/
In JS (ajax) I use that URL to which I send parameters
The snippet has to get the parameters I send. So, I really call it like this: [[!ajaxCookieList? &action=[[!#POST.action]]]]
Access to parameters in snippets is possible like this: $option = $modx->getOption('action', $scriptProperties, 'default_value', true);
I do my stuff in the snippet
But in your case, I think, everything can be simpler. You use one of the pdoTools snippets and if I am not mistaken, you can just place pdoResources snippet call on a page (/page-with-snippet/) like this:
[[pdoResources?
&parents=`6`
&resources=`[[!addToCookieLIst? &value=`[[!#POST.action]]` ]]` // your snippet should return comma-separated list of resources` ids that you pass then to pdoResources
&tpl=`popup.favorites.item`
&includeTVs=`header.bgImage,franchise.logo,franchise.price,title,subtitle`
&prepareTVs=`1`
&hideContainers=`1`
]]
and now you can send parameters to this page (/page-with-snippet/) via AJAX and get the results if there are any. I hope I didn't mess anything - you had better check it again, but you get the idea at least :) BTW, check this article on modx.com that teaches how to write a good snippet.
Also another minor issue: as it has been pointed out here, the use of window.location is preferable to document.location.
Here is another solution I did. I used pdoResources. Hope that you will understand my code and customize it for yourselves.
Create snippet ajaxCookieList
Paste JS-code in your custom.js file
Simple markup for resources. Insert it in the chunk:
Add to wish list
Remove from wish list
Thas all:)

Refresh cart_fragments(mini-cart) by PHP or jQuery?

Im trying to update the mini-cart (cart_fragments) after/on an ajax event. It works like this.
HTML Trigger:
<a id="woomps-button-\'.$nr.\'" class="woomps-button" '.$ajax_url.' data-button-nr="'.$nr.'">
jQuery request:
jQuery( document ).on('click', '.woomps-button', function() {
var nr= jQuery(this).data('button-nr');
jQuery.ajax({
url : subpost.ajax_url,
type : 'post',
data : {
action : 'woomps_update_nr',
security : subpost.security,
nr: nr
},
success : function( response ) {
window.alert(nr);
//MAYBE_code to refresh_fragments here
}
});
return false;
});
PHP responder:
function woomps_update_choosen_person () {
$p = $_POST['nr'];
if ($p == 1) {$x= "This must show in cart";}
WC()->session->set( 'woomps_limit_by_persons' , $x );
//MAYBE code to refresh_fragments here
}
And in the mini-cart.php template i have a calculation based on this field.
$items_left_start = WC()->session->get( 'woomps_limit_by_persons' )?: 3 ;
//Do something something here
So this works, except I need to refresh the cart like when an item is added to cart. My assumption is that is should be an ajax request from jQuery that i can put in the success block?
The class i (think) I want to fire is this WC_AJAX::get_refreshed_fragments(); But this is fired from an an add_action, so i tried this add_action( 'wp_ajax_nopriv_woocommerce_get_refreshed_fragments', array( 'WC_AJAX', 'get_refreshed_fragments' ) );. But it did not work either.
I also try to create an jQuery ajax call like it does in the add_to_cart button, but it neither worked.
//MAYBE_code to refresh_fragments here
var data = {};
jQuery.post(
wc_get_refreshed_fragments_params.wc_ajax_url.toString().
replace( '%%endpoint%%', 'get_refreshed_fragments' ), data,
function( response ){
})
}
I do not completely understand how this works, if anyone have some pointers or a snippet i would so much appriciate it. Been struggeling with this for some time now.
After much struggeling this topic on stack helped create the correct code to update mini cart fragments. It was both PHP and jQuery neeeded.
So basically you can call the WC_AJAX::get_refreshed_fragments() at the end of your PHP coode responder; if it comes from an AJAX call. It will not return to your PHP responder code so put it at the end. The PHP respons will end/sent back to jQuery inside the WC_AJAX::get_refreshed_fragments(); so you also need to create some jQuery that responds to this. This i got from the topic:
var fragments = response.fragments;
if ( fragments ) {
jQuery.each(fragments, function(key, value) {
jQuery(key).replaceWith(value);
});
}

jQuery Related Selects pass additional param

Here's the most basic code of it (i'm using this)
$("form").relatedSelects({
onChangeLoad: 'datasupplier.php',
selects: ['stateID', 'countyID', 'townID', 'villageID']
});
i need to pass several more parameter for some reason. my usual ajax code is something like this
$.post("ajax/template.php", {myparams: $("#myparams").val(), action: "SEARCH_MEMBER_DETAILS" },
function (data){
var returnCode = data.returnCode;
if (returnCode == "1"){
$("#data").val(data.name);
}
},"json");
question is, how do I send the params like myparams and action to the jQuery Related Selects code?
i tried something like
$("form").relatedSelects({
onChangeLoad: 'datasupplier.php',
data: {action: "SEARCH_MEMBER_DETAILS"},
selects: ['stateID', 'countyID', 'townID', 'villageID']
});
but it seems the additional params are not sent
The relatedScripts plugin does not provide any facility to manipulate the ajax request.
But it is possible to alter it slightly to achieve the requirement.
If you are ready to make a change in the plugin do the following steps
In the populate($caller,$select,o) method of the plugin make the following change
beforeSend: function(){
return o.onLoadingStart.apply($select, Array.prototype.slice.call(arguments,0));
},
It is now beforeSend: function(){ o.onLoadingStart.call($select); },
Then change your script like
$("#example-2").relatedSelects({
onChangeLoad : 'datasupplier.php',
loadingMessage : 'Please wait',
selects : ['stateID', 'countyID', 'townID', 'villageID'],
onLoadingStart : function(jqxhr, settings) {
console.log('st', arguments, settings.url);
settings.url += '&t=tttt'
}
});
Demo: Fiddle
I've went through the documentation of the plugin and seems that there's not a way to achieve what you need.
If you don't want to extend the plugin and implement the functionality by yourself, you can try by creating the parameter inside the onChangeLoad and pass them as GET parameter like this:
$("form").relatedSelects({
onChangeLoad: 'datasupplier.php?myparams='+$("myparams").val()+'&action=SEARCH_MEMBER_DETAILS',
selects: ['stateID', 'countyID', 'townID', 'villageID']
});

Using JSON to update a custom post type in Wordpress

I have a custom post type, lets call it products. When a user drags this product to the shopping cart (droppable jQuery UI), I want the key called "amount" in my custom post type to reduce by one.
So far I have a JSON function via jQuery $.ajax that looks like this:
$.ajax({ url: 'http://localhost:8888/MAMP/nogg/wordpress/wp-content/themes/twentyeleven/functions.php',
data: { postid: +id },
type: 'post',
success: function(output) {
alert("amount is reduced by 1.");
}
});
This send the id of the post to functions.php, then I use this to get the data in my functions.php
if(isset($_POST['postid']) && !empty($_POST['postid'])) {
$postid = $_POST['postid'];
$response = json_decode($postid);
remove_amount($response);
}
Which calls the function with the postid.
function remove_amount($postid) {
$amount = get_post_meta($postid, 'amount', true);
update_post_meta($postid, 'amount', $amount--);
}
This gives me a 500 error, I've made sure it's the correct ID that has been sent, and checked the name of the field containing the key (amount).
So what is my dumb self missing here?
You do not need to json_decode the $_POST['postid'] variable.
The $.ajax method serializes your data object and sends the data in your request header just like a regular POST. jQuery isn't sending JSON to your server. (You could change your ajax parameters to actually send JSON, but I wouldn't complicate your life over a wordpress install. The way you are using $.ajax is fine.)
Try it like this:
if(isset($_POST['postid']) && !empty($_POST['postid'])) {
// Make sure you do something in this function to prevent SQL injection.
remove_amount($_POST['postid']);
}
Also, what's with the +id in your data object? Is that intentional? Other than that you'll need to give us the PHP error that is causing the HTTP 500.
get_post_meta returns a string if you've set the $single param to true, which you have.
So, is your error related to trying to decrement a string value?
What about casting your amount val to an int before decrementing it?
function remove_amount($postid) {
(int)$amount = get_post_meta($postid, 'amount', true);
update_post_meta($postid, 'amount', $amount--);
}
Does the line of the error message you are getting (706) correspond to the line where you are handling your update meta?
Ok, I solved it. Apparently there's something in the WP functions file that doesn't approve of handling json content like that. Hence not recognizing the standard WP-functions (like get_post_meta), what I did was to create a blank page, had it use a custom template with the php code, then in the jquery code I linked to that WP-page.
$.ajax({ url: 'http://localhost:8888/MAMP/nogg/wordpress/?page_id=43',
data: {postid2: id },
type: 'post',
success: function(output) {
}
});
and page_id=43 is a page using the template below:
<?php
/**
* Template Name: ajax template
* Description: ajax *
* #package WordPress
*/
if(isset($_POST['postid']) && !empty($_POST['postid'])) {
remove_amount($_POST['postid']);
}
function remove_amount($postid) {
$amount = get_post_meta($postid, 'amount', true);
if($amount > 0):
update_post_meta($postid, 'amount', $amount-1);
echo $amount-1;
endif;
}
Now the code runs as it should, now I just need to do what Stephen said and add some sql-injection protection. Thanks for the answers! Got me in the right direction!

jQuery Connected Sortable Lists, Save Order to MySQL

Hoping that using something like this demo it is possible to drag items within and between two columns, and update their order either live or with a "save" button to MySQL. Point being that you can make changes and return to the page later to view or update your ordering.
http://pilotmade.com/examples/draggable/
Doing it for just one column is fine, but when I try to pass the order of both columns, the issue seems to be passing multiple serialized arrays with jQuery to a PHP/MySQL update script.
Any insight would be much appreciated.
If you look below, I want to pass say...
sortable1entry_1 => 0entry_5 => 1
sortable2entry_3 => 0entry_2 => 1entry_4 => 2
EDIT: This ended up doing the trick
HTML
<ol id="sortable1"><li id="entry_####">blah</li></ol>
jQuery
<script type="text/javascript">
$(function()
{
$("#sortable1, #sortable2").sortable(
{
connectWith: '.connectedSortable',
update : function ()
{
$.ajax(
{
type: "POST",
url: "phpscript",
data:
{
sort1:$("#sortable1").sortable('serialize'),
sort2:$("#sortable2").sortable('serialize')
},
success: function(html)
{
$('.success').fadeIn(500);
$('.success').fadeOut(500);
}
});
}
}).disableSelection();
});
This is the PHP query
parse_str($_REQUEST['sort1'], $sort1);
foreach($sort1['entry'] as $key=>$value)
{
do stuff
}
what I would do is split them up
data :
{
sort1:$('#sortable1').sortable('serialize'),
sort2:$('#sortable2').sortable('serialize')
}
then when you post you can get the request and set them as needed, I hope that makes sense
so what I do is this
parse_str($_REQUEST['sort1'],$sort1);
foreach($sort1 as $key=>$value){
//do sutff;
}

Categories