wake-up-neo.net

Ermöglichen, dass admin-ajax.php "application/json" anstelle von "x-www-form-urlencoded" empfängt

Ich benutze die AngularJS-Funktion $http, um meine Nutzdaten an das WordPress-Subsystem admin-ajax.php zu senden, aber es scheint, dass dieses nur x-www-form-urlencoded-Daten anstelle des von Angular bereitgestellten application/json akzeptiert.

Ich weiß, es gibt Möglichkeiten wie $ http eher wie $.post() funktionieren kann, aber das ist unsinnig - warum sollte man eine Reihe von JSON-Daten in ein Formular umwandeln, wenn es bereits JSON ist?

Zu diesem Zweck - gibt es eine Möglichkeit, admin-ajax anzuweisen, Typ als application/JSON anstelle von x-www-form-urlencoded zu konsumieren?

3
aendrew

es scheint, dass letztere nur x-www-form-urlencoded akzeptiert

Das stimmt nicht ganz.

WordPress admin-ajax.php übernimmt die Aktion von $_REQUEST['action'] und $_REQUEST ist gleich:

array_merge($_POST, $_GET);

Was jedoch viele Leute nicht merken, ist, dass $_GET in PHP not ist. Die Daten wurden mit der HTTP-GET-Methode an die Seite gesendet. Tatsächlich können Sie jede HTTP-Methode (POST, PUT, DELETE ...) und welcher Inhaltstyp auch immer sowie $_GET enthalten immer Daten, die Sie an die URL-Abfragezeichenfolge übergeben.

Wenn Sie also eine Anfrage an wp-admin/admin-ajax.php?action=awesome_action senden, wird "awesome_action" immer erreicht, unabhängig von der verwendeten HTTP-Methode und dem HTTP-Inhaltstyp.

Kurz gesagt, wenn Sie in der Lage sind, das Argument action mit der URL zu senden, können Sie admin-ajax.php verwenden, um alle JSON-Daten und HTTP-Methoden zu senden. Dann ist Ihr Problem, diese zu behandeln.

Mit php://input stream ist das jedoch ganz einfach.

Beispiel

Zunächst schreibe ich eine Funktion, die curl verwendet, um eine HTTP-Anfrage mit JSON-Inhaltstyp zu senden (da ich hier keinen Angular-Code schreiben möchte):

/**
 * @param string $url  Url for for the request
 * @param string $data JSON-encoded data to send
 */
function mySendJson($url, $data)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); // PUT HTTP method
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',           // JSON content type
        'Content-Length: ' . strlen($data))
    );
    return curl_exec($ch);
}

Ziemlich einfach.

Jetzt werde ich zu Testzwecken eine Funktion in die Frontend-Fußzeile einfügen, die eine HTTP-Anfrage mit JSON-Inhaltstyp sendet, wobei die oben genannte Funktion verwendet wird, und etwas JSON zurückerwartet:

add_action('wp_footer', function() {

    $ajax_url = admin_url('admin-ajax.php?action=json-test');

    // some dummy json data
    $data = array("name" => "Giuseppe", "country" => "Italy");
    $json = json_encode($data);

    // Using curl we simulate send HTTP request with json content type
    // in your case is Angular that perform the request
    $json_response = mySendJson($ajax_url, $json);

    echo '<pre>';
    print_r(json_decode($json_response, true));
    echo '</pre>';
});

Wenn nun admin-ajax.php angefordert wird, wird nach Rückrufen gesucht, die an 'wp_ajax_json-test' hook (oder 'wp_ajax_nopriv_json-test') für nicht angemeldete Benutzer angehängt sind.

Fügen wir diesen Hooks eine benutzerdefinierte Funktion hinzu:

add_action('wp_ajax_json-test', 'myWpAjaxTest');
add_action('wp_ajax_nopriv_json-test', 'myWpAjaxTest');

Die Funktion myWpAjaxTest() wird von WordPress aufgerufen, wenn die HTTP-Anfrage mit dem Inhaltstyp JSON an admin-ajax.php gesendet wird.

Schreiben wir es:

function myWpAjaxTest() {
    // Retrieve HTTP method
    $method = filter_input(INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING);
    // Retrieve JSON payload
    $data = json_decode(file_get_contents('php://input'));

    // do something intersting with data,
    // maybe something different depending on HTTP method

    wp_send_json(array(  // send JSON back
      'method'        => $method,
      'data_received' => $data
    ));
}

Dank php://input ( docs ) letzte Funktion

  • analysiert die JSON-Daten, die an admin-ajax.php gesendet wurden
  • manipuliert es
  • sendet eine JSON-Antwort zurück (weil wp_send_jsonden json-Inhaltstyp verwendet )

Wenn Sie sich die Themenfußzeile ansehen, werden Sie als Endergebnis Folgendes finden:

Array
(
    [method] => PUT
    [data_received] => Array
        (
            [name] => Giuseppe
            [country] => Italy
        )

)
6
gmazzap

admin-ajax.php wurde für die Arbeit mit jQuery entwickelt. Wenn Sie die Konvertierung nicht auf der JS-Site durchführen, müssen Sie sie auf dem Server ausführen, damit sie funktioniert. Stattdessen können Sie Ihren eigenen "Endpunkt" hinzufügen, der json verarbeiten kann. Das größte Problem bei diesem Ansatz ist die Abfrage, dass WP auf "Front-End" -URLs ausgeführt wird.

0
Mark Kaplun