web-dev-qa-db-fra.com

Créer un backend Ajax pour un modèle de page spécialisé? Est-ce que admin-ajax.php devrait être utilisé?

Nous envisageons un projet à venir qui nécessitera le développement d'une application Web php volumineuse au sein d'un site wordpress existant - ceci est destiné uniquement à notre utilisation et nous n'avons pas l'intention d'essayer de le présenter à d'autres utilisateurs; donc, l'interopérabilité n'est pas vraiment une préoccupation tant que nous pouvons continuer à appliquer les mises à jour WordPress dès leur publication sans casser notre application.

Notre idée initiale est de coder l'application sous la forme d'un fichier php unique situé dans le dossier du thème, sous la forme d'un ' Modèle de page spécialisé '.

La principale raison en est d’utiliser les fonctions de rôle, de fonctionnalité et d’authentification déjà disponibles dans Wordpress.

Ce sera une application Web relativement grande comprenant des objets, des classes et des milliers de lignes sur mesure de code sur mesure, JQuery et TSQL.

Une partie de cette application Web consistera en un gros back-end de fonctions ajax (environ 120 environ) - ma question concerne ce fichier dorsal ajax.

Nous préférerions gérer nous-mêmes le comportement de connexion et de déconnexion au niveau ajax, car nous ajouterons des fonctionnalités et une authentification supplémentaires aux requêtes ajax en fonction des restrictions de rôle et de capacité.

Notre question:

Si nous écrivons notre propre fichier ajax.php, quels fichiers wp devons-nous require_once() pour assurer l’accès aux fonctions et objets de base de wordpress (tels que is_user_logged_in(), current_user_can() & $current_user etc)

Quel est notre problème avec admin-ajax.php je vous entends demander?

Un exemple typique de demande ajax que nous allons effectuer consiste à mettre à jour une valeur unique dans la base de données, qui se compose de 3 étapes simples:

  • Vérifier que l'utilisateur est authentifié, sinon renvoyer un en-tête 403 et exit ();
  • Initialiser notre classe de base de données d'applications et exécuter l'instruction tsql
  • retourne 200 en-tête

Très simple comme vous pouvez le voir et pourrait être fait avec un peu jquery côté client et 3 lignes de php côté serveur, pour faire la même chose avec admin-ajax nous avons besoin de creuser avec wp_localize_script, add_action, wp_enqueue_script avant même d’écrire le client- côté JQuery (ou avons-nous mal compris?) - cela semble juste un peu "exagéré"?

5
HeavenCore

Implémentation personnalisée par rapport à l'utilisation de l'API standard

L'utilisation de l'API WP AJAX est la solution. Tout d’abord, vous avez accès à l’ensemble complet des API WP, vous pouvez exploiter les appels jQuery $.ajax() standard et similaires, et vous exécutez une conformité standard et accédez à toutes les connaissances réparties sur le Web avec des articles ou pour par exemple en réponses sur ce site. À court terme, vous pourriez penser que vous êtes plus rapide, mais à long terme, vous ne faites que vous isoler de toutes les sources d'aide.

Exemple: débogage

Vous devrez implémenter des itinéraires de débogage personnalisés, tandis que WordPress AJAX possède de nombreuses de sources qui vous aideront à vous en sortir.

Base de données externe

La meilleure chose à faire est d’utiliser la classe $wpdb .

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

Plus d'infos dans cette réponse .

Aérien?

Le principal inconvénient "problème"/performances lors de l’utilisation de WP AJAX est que chaque demande adressée à admin-ajax.php recharge en réalité l’ensemble du cœur de WordPress. Ce fichier peut être remplacé, comme indiqué par @Rarst dans cette réponse par un fichier personnalisé qui réduit l'impact et ne charge que ce dont vous avez besoin.

Application personnalisée

Comme je le fais au jour le jour: cela ne pose aucun problème de développer votre application en dehors de WordPress et de la simplement extraire via Composer (ou le gestionnaire de paquets que vous utilisez) et de la charger à partir d'un simple fichier dans votre dossier de plugins cela n'a rien de plus qu'un appel nécessitant notre autochargeur, un contrôleur et un commentaire d'en-tête qui le déclare comme un plugin.

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

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

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

C'est tout ce dont vous avez besoin.

Des applications Web

Si vous utilisez un fichier Angular.js, Ember ou Backbone WeApp ce n'est pas un problème. WP AJAX fonctionnera avec cela sans problème.

Sécurité

WordPress réutilise ses notes, ce qui est un fait bien connu. Cela n'expose pas vraiment ou n'ouvre pas un ensemble de sécurité, mais vous pouvez aller encore plus loin et générer un nouveau nonce [pour chaque demande également], en passant vos appels ... en toute sécurité.

Les bases

Comme il n’est pas logique de répéter d’autres réponses, il suffit de lire ajax , regardez mon exemple GitHub Gist ou mon autre GitHub Gist qui montre différentes implémentations pour montrer que les rappels peuvent être attaché de toutes les manières possibles.

Globalement, votre plugin ne fera pas plus que ce qui suit:

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

Vous venez d’enregistrer cela et votre callback AJAX et vous avez terminé:

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

Remarque: Complet exemple Gist sur la désinfection à l’aide de filter_var_array().

Et votre fichier AJAX.js ressemblera à ce qui suit:

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

Il n'y a pas grand-chose à faire à part combler les lacunes/la logique de votre application dans ce qui est montré ci-dessus dans le code.

6
kaiser

Ceci est un ajout à @kaiser answer , lisez-le avant.

Pour être honnête, wp_localize_script, add_action sont la meilleure partie de l'API Ajax et, en réalité, ils sont une aide, pas un problème.

Imaginons que vous ayez 120 fonctions ajax. Même si vous n'utilisez pas admin-ajax.php, consultez à nouveau votre flux de travail:

  • Vérifier que l'utilisateur est authentifié, sinon renvoyer un en-tête 403 et exit ();
  • Initialiser notre classe de base de données d'applications et exécuter l'instruction SQL
  • retourne 200 en-tête

la partie "core" est "execute sql statement" qui est une action, parmi 120.

Comment choisissez-vous l'action à effectuer? Voulez-vous créer 200 points d’entrée ajax? J'espère que non. Je pense que vous allez créer un fichier de point d’entrée unique et, en utilisant un argument de requête, $_POST['action'] ou similaire, vous décidez quelle action exécuter.

En utilisant 'wp_ajax_*' et 'wp_ajax_nopriv_*', vous avez déjà un code intégré qui dispatch une demande à l'action associée interprète (une méthode objet, un rappel, etc.).

De plus, si vous utilisez uniquement 'wp_ajax_*' sans 'wp_ajax_nopriv_*', la procédure d'authentification est déjà incluse, vous n'avez rien d'autre à faire (ou vous pouvez peut-être utiliser 'wp_ajax_nopriv_*' pour envoyer l'en-tête 403).

Parlons de wp_localize_script.

Tout d 'abord, vous devrez passer les variables de PHP à javascript . Comment allez-vous gérer cette tâche? Mettre javascript dans les fichiers php et utiliser echo dans le code js? J'espère que non. En fait, wp_localize_script vous offre un moyen pratique de travailler, sans avoir à écrire de code personnalisé et à concentrer vos efforts sur l'écriture de votre logique métier.

Le premier endroit où vous devez passer des données de PHP à js est le moment où vous devez implémenter la protection CSRF. Votre flux de travail en 3 points ci-dessus n’est en fait ni complet ni sécurisé: l’authentification se fait via un cookie et est donc vulnérable à Falsification de requêtes intersites . Les moyens utilisés par WordPress pour empêcher ce type d'attaques sont nonces des chaînes aléatoires de courte durée que les attaquants ne peuvent prédire. Ces informations sont générées dans PHP comment voulez-vous transmettre ces variables à js?

Maintenant la mauvaise partie: oui, WordPress ajax est lent . Comme @ kaiser dans sa réponse, vous pouvez créer votre propre point d’entrée en évitant de charger des choses dont vous n’avez pas besoin, comme des widgets, des thèmes et d’autres choses. Mais dans ce fichier, je suggère de déclencher tous les points d'ancrage WordPress et, en général, d'essayer de conserver la compatibilité WordPress. Pourquoi?

C'est simple: même si vous ne voulez pas distribuer votre code, vous pouvez arriver un jour où vous voulez utiliser un plugin WordPress: il y en a des milliers là-bas ... n'est pas bien d'avoir la possibilité d'en utiliser des plugins pour faire des choses au lieu de réinventer la roue à chaque fois que vous avez besoin de quelque chose?

4
gmazzap