web-dev-qa-db-ja.com

Specialized Page Template用のAjaxバックエンドを作成しますか? admin-ajax.phpを使うべきですか?

私たちは既存のワードプレスサイト内で大規模なphpウェブアプリケーションの開発を必要とする今後のプロジェクトを予定しています - これは私たちの使用のためだけであり、他のユーザーのためにそれをパッケージ化することを試みません。そのため、アプリケーションを壊すことなくWordPressのアップデートがリリースされるまで適用し続けることができれば、相互運用性は実際には問題になりません。

私たちの最初の考えは ' Specialized Page Template 'としてテーマフォルダ内にある単一のphpファイルとしてアプリケーションをコーディングすることです。

これの主な理由はWordpressの中ですでに利用可能な役割、機能と認証機能を利用することです。

これは、特注のオブジェクト、クラス、そして特注のphp、JQuery、およびTSQLコードの1000行からなる比較的大きなWebアプリケーションになります。

このWebアプリケーションの一部は、ajax関数の大規模なバックエンド(約120)になります。私の質問は、このajaxバックエンドファイルに関連しています。

ロールと機能の制限に基づいて追加の機能と認証をajaxリクエストに追加するので、ログインとログアウトの動作を自分自身でa​​jaxレベルで処理することをお勧めします。

私達の質問:

もし私達が私達自身のajax.phpファイルを書くなら、どのwpファイルが私達はwordpressの中心的な機能とオブジェクト(例えばrequire_once()is_user_logged_in()$current_userなど)へのアクセスを確実にするためにcurrent_user_can()にする必要があります

admin-ajax.phpに問題がありました。

これから行うajaxリクエストの典型的な例は、データベース内の単一の値を更新することです。これは、3つの簡単なステップで構成されます。

  • ユーザが認証されたかどうかを確認し、そうでなければ、403ヘッダを返してexit();
  • アプリケーションデータベースクラスを初期化してtsql文を実行する
  • 200ヘッダを返す

あなたが見ることができるように非常に単純ですそして私達がクライアントを書くことになる前に我々はwp_localize_script、add_action、wp_enqueue_scriptを通して掘る必要があるadmin-ajaxで同じことをするためにside JQuery(あるいは私たちが誤解したことがありますか?) - それはちょっと "やり過ぎ"のようですか?

5
HeavenCore

カスタム実装と標準APIの使用

WP AJAX AP​​Iを使用する方法があります。最初に、WP AP​​Iの完全なセットにアクセスし、標準のjQuery $.ajax()および同様のAPI呼び出しを活用し、標準準拠を実行して、Web全体に広がるすべての知識にアクセスします。記事付きまたはこのサイトの回答で。短期的には、自分のほうが速いと思うかもしれませんが、長期的には、すべてのヘルプソースから自分を切り離しているだけです。

例:デバッグ

カスタムデバッグルートを実装する必要がありますが、WordPress AJAXには多くの ソース があり、それを回避するのに役立ちます。

外部データベース

最善の方法は、 $wpdb クラスを使用することです。

class CustomDatabaseHandler extends wpdb
{
    // Overwrite what you need here
}

詳細 この回答では

オーバーヘッド?

WP AJAXを使用する場合の主な「問題」/パフォーマンスの欠点は、admin-ajax.phpへのすべてのリクエストが実際にWordPressコア全体をリロードすることです。 この回答では@Rarstによる に示すように、このファイルは、影響を軽減し、必要なものだけをロードするカスタムファイルに置き換えることができます。

カスタムアプリケーション

私は日常的にそれをやっているので、WordPressの外でアプリケーションを開発し、Composer(または使用しているパッケージマネージャー)を介して単純にそれを取り込むのは問題ありませんプラグインフォルダー内のシンプルな単一ファイルからロードします。このファイルには、オートローダー、コントローラー、およびプラグインとして宣言するヘッダーコメントが必要です。

<?php
/** Plugin Name: Custom Application as Plugin */

# Composer autoloader
include_once __DIR__.'/vendor/autoload.php';

add_action( 'plugins_loaded', function()
{
    // Initialize your plugin here
} );

必要なのはそれだけです。

Webアプリケーション

Angular.js、Emberまたは Backbone WeApp を実行している場合は問題ありません。 WP AJAXは問題なく動作します。

セキュリティ

WordPressはそのナンスを再利用しますが、これはよく知られている事実です。これは実際には何も公開したり、セキュリティ全体を公開したりすることはありませんが、さらに一歩進んで(すべてのリクエストに対して)新しいnonceを生成し、呼び出しを行うことができます。

基礎

他の答えを繰り返すのは理にかなっていないので、単に ajax を読み、 私の例のGitHub Gist または 私の他のGitHub Gist を見てくださいさまざまな実装を示して、可能な方法でコールバックをアタッチできることを示しています。

全体的に、プラグインは次のこと以上のことはしません。

// Public or private?
// 'wp_enqueue_scripts'/'admin_enqueue_scripts'
// or only on login?
// 'login_enqueue_scripts'
add_action( 'wp_enqueue_scripts', function()
{
    $name = 'handle';
    wp_register_script(
        $name,
        plugins_url( 'assets/ajax.js', __FILE__ ),
        [ 'jquery' ],
        filemtime( plugins_dir_path( __FILE__ ).'assets/ajax.js' ),
        true
    );
    wp_enqueue_script( $name );
    wp_localize_script(
        $name,
        "{$name}Obj", // This string is what gives you access to below array
        [
            'ajaxurl'     => admin_url( 'admin-ajax.php' ),
            '_ajax_nonce' => wp_create_nonce( "{$name}_action" ),
            'action'      => "{$name}_action",
            'data'        => [ /* additional data as array */ ],
        ]
    );
} );

それとあなたのAJAXコールバックを登録するだけで完了です:

// Public or private?
add_action( "wp_ajax_{$name}_action", 'ajaxCb' );
add_action( "wp_ajax_nopriv_{$name}_action", 'ajaxCb' );

public function ajaxCb( $data )
{
    check_ajax_referer( $data['action'] );

    # @TODO sanitize data here:
    // filter_var() filter_var_array() and filter_input()
    # @TODO Custom logic here

    // Error?
    if ( is_wp_error( $thing ) )
        wp_send_json_error( $data );

    // Success!
    wp_send_json_success( $data );
}

注:包括的な 例の要点filter_var_array()を使用してサニタイズする方法について

そして、AJAX.jsファイルは次のようになります。

/*global jQuery, $, handleObj */
( function( $, plugin ) {
    "use strict";
        var pass = $( '#password__field' ).val(),
            name = $( '#name__field' ).val();

        // @TODO other setup tasks for static vars in here

        $.ajax( {
            url  : plugin.ajaxurl,
            data : {
                action      : plugin.action,
                _ajax_nonce : plugin._ajax_nonce,
                userName    : name,
                passWord    : pass
            },
            beforeSend : function( d ) {
                // @TODO Add loading animation
            }
        } )
            .done( function( response, textStatus, jqXHR ) {
                // @TODO Clear loading animation
                if ( ! response.success ) {
                    // @TODO Custom error
                }
                else {
                    // @TODO success
                }
            } )
            .fail( function( jqXHR, textStatus, errorThrown ) {
                console.log( errorThrown );
            } );
} ( jQuery, handleObj || {} ) );

上記のコードで示したものにギャップ/アプリケーションロジックを埋めることを除けば、実際にはこれ以上のことはありません。

6
kaiser

これは @ kaiser answer のアドオンです。前に読んでください。

正直に言うと、wp_localize_scriptadd_actionはAjax APIの最も優れた部分であり、実際には問題ではなく助けになります。

120個のAjax関数があるとしましょう。 admin-ajax.phpを使用しない場合でも、ワークフローをもう一度確認してください。

  • ユーザーが認証されていることを確認し、認証されていない場合は、403ヘッダーとexit()を返します。
  • アプリケーションデータベースクラスを初期化し、SQLステートメントを実行する
  • 200ヘッダーを返します

「コア」部分は、120の内の1つであるアクションである「SQLステートメントの実行」です。

実行するアクションをどのように選択しますか? 200個のAjaxエントリポイントを作成しますか?いいえ単一のエントリポイントファイルを作成し、リクエスト引数$_POST['action']などを使用して、実行するアクションを決定すると思います。

'wp_ajax_*'および'wp_ajax_nopriv_*'を使用すると、dispatch関連アクションperformer(オブジェクトメソッド、コールバックなど)。

さらに、'wp_ajax_*'なしで'wp_ajax_nopriv_*'のみを使用する場合、認証ルーチンが既に含まれているため、他に何もする必要はありません(または、'wp_ajax_nopriv_*'を使用して403ヘッダーを送信できます)。

wp_localize_scriptについて話しましょう。

最初にまたは後で変数フォームPHP_をjavascriptに渡す必要があります。このタスクをどのように処理しますか? JavaScriptをphpファイル内に配置し、jsコード内でechoを使用しますか?いいえ実際、wp_localize_scriptは、カスタムコードを記述し、ビジネスロジックの記述に努力を集中することなく、トリックを行う便利な方法を提供します。

PHPからjsにデータを渡す必要がある最初の場所は、CSRF保護を実装する必要がある場合です。上記の3ポイントワークフローは、実際には完全でも安全でもありません。認証はCookieを介して行われるため、 クロスサイトリクエストフォージェリ に対して脆弱です。 WordPressがこの種の攻撃を防ぐ方法は nonce で、これは攻撃者が予測できない短命のランダム文字列です。これらのナンスはPHPで生成されます。どのようにしてその変数をjsに渡しますか?

悪い部分:はい、WordPress ajaxは遅い@ kaiserが彼の答えで言ったように、ウィジェットやテーマなどの不要なものをロードすることを避けて、独自のエントリポイントを作成できます。しかし、そのファイルでは、すべてのWordPressフックをトリガーし、一般的にWordPress互換性を維持することをお勧めします。どうして?

それは簡単です:コードを配布したくない場合でも、コードが到着する可能性がありますyo WordPressプラグインを使用したい:そこには数千あります...あなたが何かを必要とするたびにホイールを再発明する代わりに、物事を行うためにいくつかのプラグインを使用する可能性を持っていますか?

4
gmazzap