it-swarm.com.de

Erstellen eines Ajax-Backends für eine spezialisierte Seitenvorlage? Sollte admin-ajax.php verwendet werden?

Wir planen ein bevorstehendes Projekt, das die Entwicklung einer großen PHP-Webanwendung innerhalb einer vorhandenen WordPress-Site erfordert. Dies ist nur für unseren Gebrauch und wir haben nicht die Absicht, es für andere Benutzer zu packen. Interoperabilität ist also kein Problem, solange wir weiterhin WordPress-Updates anwenden können, wenn sie veröffentlicht werden, ohne unsere Anwendung zu beschädigen.

Unser erster Gedanke ist, die Anwendung als eine einzige PHP-Datei zu codieren, die sich im Theme-Ordner als ' Specialized Page Template ' befindet.

Der Hauptgrund dafür ist, die Funktionen für Rollen, Funktionen und Authentifizierung zu nutzen, die bereits in Wordpress verfügbar sind.

Dies wird eine relativ große Webanwendung sein, die aus maßgeschneiderten Objekten, Klassen und Tausenden von Zeilen mit maßgeschneidertem PHP-, JQuery- und TSQL-Code besteht.

Teil dieser Webanwendung wird ein großes Backend von Ajax-Funktionen sein (ca. 120) - meine Frage bezieht sich auf diese Ajax-Backend-Datei.

Wir würden es vorziehen, das Verhalten "Angemeldet" und "Abgemeldet" auf Ajax-Ebene selbst zu behandeln, da wir Ajax-Anforderungen basierend auf Rollen- und Funktionseinschränkungen um zusätzliche Funktionen und Authentifizierung erweitern.

Unsere Frage:

Wenn wir unsere eigene ajax.php-Datei schreiben, welche wp-Dateien müssen wir für require_once() verwenden, um den Zugriff auf WordPress-Kernfunktionen und -Objekte sicherzustellen (wie is_user_logged_in(), current_user_can() & $current_user etc)

Was ist unser Problem mit admin-ajax.php?

Ein typisches Beispiel für eine Ajax-Anfrage ist das Aktualisieren eines einzelnen Wertes in der Datenbank, der aus drei einfachen Schritten besteht:

  • Überprüfen Sie, ob der Benutzer authentifiziert ist. Wenn nicht, geben Sie einen 403-Header zurück und beenden Sie ().
  • Initialisieren Sie unsere Anwendungsdatenbankklasse und führen Sie die Anweisung tsql aus
  • 200 Header zurückgeben

Sehr einfach, wie Sie sehen und mit ein wenig clientseitiger jquery und 3 Zeilen serverseitigem php erledigt werden können. Um dasselbe mit admin-ajax zu tun, müssen wir erst wp_localize_script, add_action, wp_enqueue_script durcharbeiten, bevor wir überhaupt mit dem Schreiben des clientseitigen php beginnen können. Seite JQuery (oder haben wir falsch verstanden?) - es scheint nur ein wenig "Overkill"?

5
HeavenCore

Benutzerdefinierte Implementierung im Vergleich zur Standard-API-Verwendung

Die Verwendung der WP AJAX-API ist der richtige Weg. Zuallererst erhalten Sie Zugriff auf alle WP APIs, können standardmäßige jQuery $.ajax()- und ähnliche API-Aufrufe nutzen und werden standardkonform ausgeführt und erhalten Zugriff auf alle Informationen, die im Internet mit Artikeln oder für verbreitet werden z.B in Antworten auf dieser Seite. Kurzfristig denken Sie vielleicht, dass Sie schneller sind, aber auf lange Sicht schneiden Sie sich einfach von allen Hilfsquellen ab.

Beispiel: Debuggen

Sie müssen benutzerdefinierte Debugging-Routen implementieren, während WordPress AJAX viele Quellen enthält, die Ihnen dabei helfen, diese zu umgehen.

Externe Datenbank

Verwenden Sie am besten die Klasse $wpdb .

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

Weitere Infos in dieser Antwort .

Gemeinkosten?

Das Hauptproblem/der Leistungsnachteil bei der Verwendung von WP AJAX ist, dass bei jeder Anforderung von admin-ajax.php tatsächlich der gesamte WordPress-Kern neu geladen wird. Diese Datei kann ersetzt werden, wie in dieser Antwort gezeigt von @Rarst durch eine benutzerdefinierte Datei, die die Auswirkungen verringert und nur das lädt, was Sie benötigen.

Benutzerdefinierte Anwendung

So wie ich es tagtäglich mache: Es ist kein Problem, Ihre Anwendung außerhalb von WordPress zu entwickeln und sie dann einfach über Composer (oder den von Ihnen verwendeten Paket-Manager) zu laden und aus einer einfachen einzelnen Datei in Ihren Plugins-Ordner zu laden Das erfordert lediglich einen Aufruf für unseren Autoloader, einen Controller und einen Headerkommentar, der ihn als Plugin deklariert.

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

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

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

Das ist alles was du brauchst.

Web Applikationen

Wenn Sie eine Angular.js, Ember oder Backbone WeApp ausführen, ist dies kein Problem. WP AJAX funktioniert damit problemlos.

Sicherheit

WordPress verwendet seine Nonces wieder, was eine bekannte Tatsache ist. Dies macht weder wirklich etwas sichtbar noch öffnet es ein Sicherheitsganzes, aber Sie können einen Schritt weiter gehen und eine neue Nonce generieren [auch für jede Anfrage], um Ihre Anrufe zu tätigen ... ubersicher.

Grundlagen

Da es keinen Sinn macht, andere Antworten zu wiederholen, lesen Sie einfach ajax durch, schauen Sie sich mein Beispiel für GitHub Gist oder mein anderes GitHub Gist an, das verschiedene Implementierungen zeigt, um zu zeigen, dass Callbacks möglich sind in irgendeiner Weise angebracht.

Insgesamt wird Ihr Plugin nicht viel als das Folgende tun:

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

Sie registrieren das und Ihren AJAX Rückruf und Sie sind fertig:

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

Hinweis: Umfassendes Beispiel-Handbuch zum Desinfizieren mit filter_var_array().

Und Ihre AJAX.js-Datei sieht ungefähr so ​​aus:

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

Es gibt nicht wirklich viel mehr zu tun, als die Lücken/Ihre Anwendungslogik in das oben im Code Gezeigte einzufügen.

6
kaiser

Dies ist ein Add-On zu @kaiser answer , lies das vorher.

Um ehrlich zu sein, wp_localize_script, add_action sind der beste Teil der Ajax-API, und tatsächlich sind sie eine Hilfe, kein Problem.

Stellen wir uns vor, Sie haben 120 Ajax-Funktionen. Auch wenn Sie admin-ajax.php nicht verwenden, sehen Sie Ihren Workflow erneut:

  • Überprüfen Sie, ob der Benutzer authentifiziert ist. Wenn nicht, geben Sie einen 403-Header zurück und beenden Sie ().
  • Initialisieren Sie unsere Anwendungsdatenbankklasse und führen Sie die SQL-Anweisung aus
  • 200 Header zurückgeben

der "Kern" -Teil ist "SQL-Anweisung ausführen", eine Aktion unter 120.

Wie wählst du die auszuführende Aktion aus? Möchten Sie 200 Ajax-Einstiegspunkte erstellen? Ich hoffe nicht. Ich denke, Sie werden eine einzelne Einstiegspunktdatei erstellen und mit einem Anforderungsargument, $_POST['action'] oder ähnlichem, entscheiden, welche Aktion ausgeführt werden soll.

Mit 'wp_ajax_*' und 'wp_ajax_nopriv_*' verfügen Sie bereits über einen integrierten Code, der dispatch eine Anforderung an die zugehörige Aktion performer (eine Objektmethode, einen Rückruf usw.).

Wenn Sie nur 'wp_ajax_*' ohne 'wp_ajax_nopriv_*' verwenden, ist die Authentifizierungsroutine bereits enthalten, und Sie müssen nichts weiter tun (oder Sie können 'wp_ajax_nopriv_*' zum Senden des 403-Headers verwenden).

Sprechen wir über wp_localize_script.

Erst oder später müssen Sie Variablen von PHP an javascript übergeben. Wie werden Sie diese Aufgabe bewältigen? Javascript in die PHP-Dateien einfügen und echo im js-Code verwenden? Ich hoffe nicht. Tatsächlich bietet Ihnen wp_localize_script eine bequeme Möglichkeit, diesen Trick auszuführen, ohne dass Sie benutzerdefinierten Code schreiben und sich auf das Schreiben Ihrer Geschäftslogik konzentrieren müssen.

Der erste Ort, an dem Sie Daten von PHP an js übergeben müssen, ist, wenn Sie den CSRF-Schutz implementieren müssen. Der oben beschriebene 3-Punkte-Workflow ist weder vollständig noch sicher: Die Authentifizierung erfolgt über Cookies und ist daher anfällig für Fälschungen von Cross-Site-Anfragen . Die Art und Weise, wie WordPress diese Art von Angriffen verhindert, sind nonces , kurzlebige zufällige Zeichenfolgen, die von Angreifern nicht vorhergesagt werden können. Diese Nonces werden in PHP generiert. Wie möchten Sie diese Variablen an js übergeben?

Nun der schlechte Teil: Ja, WordPress Ajax ist langsam . Wie @kaiser in seiner Antwort sagte, können Sie Ihren eigenen Einstiegspunkt erstellen und vermeiden, dass Sie Dinge laden, die Sie nicht benötigen, wie Widgets, Themen und andere Dinge. Aber in dieser Datei schlage ich vor, alle WordPress-Hooks auszulösen und im Allgemeinen zu versuchen, die WordPress-Kompatibilität beizubehalten. Warum?

Es ist ganz einfach: Auch wenn Sie Ihren Code nicht verbreiten möchten, kann es eines Tages vorkommen, dass Sie ein WordPress-Plugin verwenden möchten: Es gibt Tausende ... ist nicht in Ordnung, die Möglichkeit zu haben, einige zu verwenden Plugins, um Dinge zu tun, anstatt das Rad jedes Mal neu zu erfinden, wenn Sie etwas benötigen?

4
gmazzap