1

I've searched around a lot of topics, but couldn't find the answer. My goal is to have a HTML hyperlink calling a Javascript AJAX post request on a PHP page to run a PHP function (optionally with any amount of arguments). A lot of topics solved this problem for defined functions (with a specific name). I want to generalize the AJAX post request function in order to pass the PHP function name to the AJAX request to call it, so I can define in Javascript what PHP function to call.

This is what I have, but it goes wrong at the PHP script...

The HTML:

<a onclick="call_php('php_function_name', ['arg_1', 'arg_2']);">call</a>
<p id="demo"></p>

The Javascript:

function call_php(fname, args) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById('demo').innerHTML = this.responseText;
        }
    };
    xhttp.open('POST', 'includes/functions.php', true);
    xhttp.setRequestHeader('Content-type', 'application/json');
    xhttp.send(JSON.stringify({
        'fname': fname,
        'args': args
    }));
}

At the Javascript I'm questioning the JSON.stringify() and setRequestHeader() if it is used correctly in this case.

The PHP, which should call a function in it's file:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    //header('Content-Type: application/json');
    $post = json_decode($_POST/*, true*/);
    // DO SOMETHING TO CALL: fname(...args);
}
function php_function_name(arg_1, arg_2) {
    // A FUNCTION...
}

At the PHP I'm questioning the header('Content-Type: application/json') since it's already defined at the Javascript. But the main question is: how to write the PHP code to call the PHP function? By the way: when I print echo $post it gives a warning: json_decode() expects parameter 1 to be string, array given...

6
  • 1
    Are you searching for a PHP function like call_user_func or call_user_func_array, e.g. call_user_func_array('php_function_name', array(&$a))? Commented Mar 7, 2017 at 15:17
  • Possible duplicate of Call PHP function by name from JavaScript Commented Mar 7, 2017 at 15:21
  • What @gus27 said, although you might want to check if the function your JS is trying to call actually exists first, use method_exists() for that. Commented Mar 7, 2017 at 15:21
  • Thanks, I'll have a look at the call_user_func functions, but how do I get the post data variables name and args into that function? Commented Mar 7, 2017 at 15:32
  • 1
    Just to make sure it's clear: allowing any PHP function to be called is an extremely bad idea. Consider what would happen if I open up a JS console on your site and type something like call_php('exec', ['rm -rf /']);. Hopefully you can see that the possibilities are endless for me to really mess with your system this way. Don't try and blacklist, either, have a whitelist of allowed functions, and simply respond with "error" for any other input. Commented Mar 7, 2017 at 16:21

2 Answers 2

5

The PHP Manual states that the $_POST super global variable only contains the post arguments for post data of type application/x-www-form-urlencoded or multipart/form-data.

An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.

However, you are trying to send a post request with the body of type application/json.

To read a raw body in PHP you can do this:

$postdata = file_get_contents("php://input");

This will give you a string of the entire request body. You can then json_decode this string to get the desired JSON object.

As for the part of calling a function supplied in the request, the call_user_func_array will do the job fine. Whether or not that is something you should do is an entirely separate issue. From what I understand, you are edging on on the concept of a router and a controller.

I have writen a simple snippet of what I think you want to do:

<?php

switch ($_SERVER['REQUEST_METHOD']) {
  case 'POST':
    post_handler();
    return;
  case 'GET':
    get_handler();
    return;
  default:
    echo 'Not implemented';
    return;
}

function post_handler() {
  $raw_data = file_get_contents("php://input");
  $req_body = json_decode($raw_data, TRUE);
  call_user_func_array($req_body['function'], $req_body['args']);
}

function get_handler() {
  echo 'This page left intentionally blank.';
}

function some_function($arg1, $arg2) {
  echo $arg1.' '.$arg2;
}

?>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it works perfectly! Though, keep in mind what IMSoP commented: allowing any PHP function to be called is an extremely dangerous security issue. Don't try and blacklist, either, have a whitelist of allowed functions". But for my small project where security is not of major importance, this would do it.
1

Comment json_decode and output your $_POST by calling print_r ($_POST); you should see your data structure, if it is a simple array with data keys and values then you don't have to decode it but if the array have a single column and it's value is your data then take it's key and use it to decode the content

5 Comments

I get an interesting response, an empty array: Array ( ). Any ideas where is it going wrong?
For some reason your ajax request is not sending any data try sending it as normal data parsed manuly like this "key=value&key2=value2" and see what happens
Array ( [key] => value [key2] => value2 ) Yes, that is working fine! Why not with the json format? ;p
i don't know i had the same problem but with angularjs i solve it using formData from JQuery
Thanks, I'm always trying to do it without jQuery ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.