web-dev-qa-db-ja.com

Admin-ajax.phpが "x-www-form-urlencoded"の代わりに "application/json"を受けることを許可する

ペイロードをWordPressの$httpサブシステムに送信するためにAngularJSのadmin-ajax.php関数を使用していますが、後者はAngularが提供するx-www-form-urlencodedの代わりにapplication/jsonデータのみを受け入れるようです。

私は知っています 方法はあります $ http関数を$.post()のようにする方法はありますが、これは無意味です - なぜJSONデータの束をすでにJSONになっているときにフォームに変換するのですか?

そのために - 型をadmin-ajaxではなくapplication/JSONとして消費するようにx-www-form-urlencodedに指示する方法はありますか?

3
aendrew

後者はx-www-form-urlencodedしか受け入れないようです

それは完全に真実ではありません。

WordPress admin-ajax.php$_REQUEST['action']からアクションを取り、$_REQUESTは次のようになります。

array_merge($_POST, $_GET);

しかし、多くの人が気付いていないのは、PHPの$_GETnotHTTP GETメソッドを使用してデータがページに送信されたということです。実際、HTTPメソッド(POST、PUT、 DELETE ...)とどんなコンテンツタイプでも、そして$_GETは常にあなたがURLクエリ文字列に渡すデータを含みます。

それはあなたがwp-admin/admin-ajax.php?action=awesome_actionにリクエストを送るなら "awesome_action"はあなたが使用するHTTPメソッドやHTTPコンテンツタイプに関係なく常に到達することを意味します。

つまり、URLとともにaction引数を送信できる場合は、admin-ajax.phpを使用して任意のJSONデータと任意のHTTPメソッドを送信できます。その後、yourproblemがそれらを処理します)。

しかしphp://inputストリームを使うのはとても簡単です。

まず最初に、curlを使用してJSONコンテンツタイプのHTTPリクエストを送信する関数を作成します(ここではAngularコードを記述したくないため)。

/**
 * @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);
}

とても簡単。

さて、テスト目的のためだけに、上記の関数を使用してJSONコンテンツタイプのHTTPリクエストを送信する関数をフロントエンドフッターに入れ、JSONが戻ってくることを期待します。

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>';
});

これで、admin-ajax.phpが要求されたとき、それはログインしていないユーザーのために'wp_ajax_json-test'フック(または'wp_ajax_nopriv_json-test')にアタッチされたすべてのコールバックを探します。

これらのフックにカスタム関数を追加しましょう。

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

JSONコンテンツタイプのHTTPリクエストがadmin-ajax.phpに送信されると、関数myWpAjaxTest()がWordPressによって呼び出されます。

書きましょう。

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
    ));
}

php://inputdocs )最後の関数のおかげで

最終的に、テーマのフッターを見ると、次のようになります。

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

)
6
gmazzap

admin-ajax.phpはjQueryに対して機能するように設計されています。おそらくJSサイトで変換を行わない場合は、それを機能させるためにサーバー側で変換する必要があります。代わりに、jsonを処理できる独自の「エンドポイント」を追加することができます。このアプローチの最大の問題はWPが "フロントエンド" URLで実行されるクエリです。

0
Mark Kaplun