Route de plugin personnalisée dans Wordpress

12

D'accord, ma question est donc assez simple. J'ai besoin d'implémenter des règles de routage personnalisées pour mon plugin. Ces routes ne prendraient qu'un seul argument (donc rien de compliqué) et ressembleraient à: http://www.example.org/myroute/myargument

Et idéalement, cela appelerait une classe personnalisée et afficherait un modèle personnalisé (qui pourrait accéder directement à la classe).

Quelle est la meilleure approche pour cela? À votre santé

Fran
la source

Réponses:

15

Vous devez faire trois choses importantes:

  1. Créez une règle de réécriture personnalisée pour transformer des parties de l'URI en valeurs transmises à index.php.
  2. Ajoutez myrouteet myargumentà la liste blanche des variables de requête de WordPress, afin que WordPress ne les ignore pas simplement lorsqu'elles apparaissent dans une chaîne de requête.
  3. Rincez les règles de réécriture.

Tout d'abord, je vais recommander qu'au lieu de http://www.example.org/myroute/myargument, vous vous contentiez d'une sorte de préfixe ou de suffixe spécial pour indiquer quand l'URI doit être considéré comme l'une de ces `` routes '' spéciales. Pour les besoins de cet exemple, j'ai choisi le préfixe api, pour qu'il soit http://www.example.org/api/myroute/myargument. J'ai choisi apiparce que quand j'ai fait quelque chose de RESTful, comme ce sur quoi vous semblez travailler, c'était pour une API.

Le code

add_filter( 'rewrite_rules_array', 'my_insert_rewrite_rules' );
add_filter( 'query_vars', 'my_insert_query_vars' );
add_action( 'wp_loaded', 'my_flush_rules' );

// flush_rules() if our rules are not yet included
function my_flush_rules() {
    $rules = get_option( 'rewrite_rules' );

    if ( ! isset( $rules['api/(.*?)/(.+?)'] ) ) {
        global $wp_rewrite;
        $wp_rewrite->flush_rules();
    }
}

// Adding a new rule
function my_insert_rewrite_rules( $rules ) {
    $newrules = array();
    $newrules['api/(.*?)/(.+?)'] = 'index.php?myroute=$matches[1]&myargument=$matches[2]';
    return $newrules + $rules;
}

// Adding the id var so that WP recognizes it
function my_insert_query_vars( $vars ) {
    array_push( $vars, 'myroute', 'myargument' );
    return $vars;
}

Répartition rapide

C'est assez simple. Le modèle d'expression régulière est ajouté à une liste de toutes les règles de réécriture dans WordPress, et votre modèle personnalisé est en haut de la liste. Lorsque le modèle correspond, WordPress cesse de parcourir la liste des règles de réécriture et utilise les valeurs capturées de l'expression régulière à la place des références ( $matches[1]et $matches[2]) dans la chaîne de requête transmise à index.php.

L'ajout des variables de requête myrouteet myargumentde la liste blanche fait simplement que WordPress y prête attention plutôt que de les supprimer.

Autre moyen de «nommer» votre itinéraire personnalisé

Si vous souhaitez éviter d'utiliser /api/comme préfixe, vous pouvez utiliser une variable / champ de chaîne de requête à la place. Pour faire quelque chose comme ça, vous devez changer l'expression régulière en quelque chose comme (.*?)/(.+?)\\?api=1, puis l'ajouter en apitant que paramètre supplémentaire à l' array_push()appel effectué dans my_insert_query_vars().

Cela changerait l'itinéraire personnalisé de sorte qu'il se déclenche à tout moment api=1est le premier élément de la chaîne de requête, par exemple, il déclencherait pour http://example.com/anytext/anytext?api=1.

Ignorez l'utilisation du terme «espace de noms» - utilisez-le simplement pour plus de concision.

Si vous n'espérez pas d'espace de noms avec un préfixe ou un suffixe, vous vous retrouverez avec des modèles d'URI en collision. En effet, WordPress n'aura aucun moyen de distinguer votre modèle personnalisé de celui destiné à être une publication ou une page. Comment WordPress pourrait-il savoir qu'il myroutene s'agit pas d'une taxonomie, d'un terme ou d'une page parent?

J'espère que cela t'aides.

eddiemoya
la source
1
Remarque pratique: les règles définies dans l' my_insert_rewrite_rulesordre de définition suivent! Commencez par la règle la plus longue, puis réduisez-la par la plus simple, sinon / api / myroute remplacera / api / myroute / myargument.
emc
1
@npc C'est un point important à prendre en compte lors de la création de règles de réécriture personnalisées, elles peuvent également entrer en collision de cette façon. Dans l'exemple ci-dessus cependant, ce n'est pas un problème car / api / myroute ne serait tout simplement pas un chemin valide.
eddiemoya
Comment quelqu'un pourrait-il charger un modèle personnalisé à partir de son répertoire de plugins chaque fois que la page example.org/api/myroute/myargument est demandée?
Matt Keys
1
Voici la solution réelle et complète de wordpress: codex.wordpress.org/Rewrite_API/add_rewrite_rule
Imran Zahoor
6

Pour développer un peu ce que eddiemoya a fait ci-dessus:

Comme l'affiche originale de cette question, je voulais créer une réécriture personnalisée et également fournir un modèle personnalisé pour cette page de réécriture. Le code d'edditmoya m'a permis de démarrer dans la bonne direction et j'ai ajouté une fonction supplémentaire pour servir mon modèle personnalisé lorsque la page est consultée.

Le modèle personnalisé peut être situé n'importe où, dans mon cas, il est stocké dans le répertoire du plugin.

Je voulais aussi seulement vérifier si les règles de réécriture devaient être vidées lors de l'activation du plugin, donc je l'ai mis sur un register_activation_hook

Voir ci-dessous pour l'exemple complet de ce que j'ai fait:

MISE À JOUR simplifiée basée sur les conseils de milo

class Your_Class
{

    public function init()
    {
        add_filter( 'template_include', array( $this, 'include_template' ) );
        add_filter( 'init', array( $this, 'rewrite_rules' ) );
    }

    public function include_template( $template )
    {
        //try and get the query var we registered in our query_vars() function
        $account_page = get_query_var( 'account_page' );

        //if the query var has data, we must be on the right page, load our custom template
        if ( $account_page ) {
            return PATH_TO_PLUGIN_TEMPLATES_DIR . 'register.php';
        }

        return $template;
    }

    public function flush_rules()
    {
        $this->rewrite_rules();

        flush_rewrite_rules();
    }

    public function rewrite_rules()
    {
        add_rewrite_rule( 'account/(.+?)/?$', 'index.php?account_page=$matches[1]', 'top');
        add_rewrite_tag( '%account_page%', '([^&]+)' );
    }

}

add_action( 'plugins_loaded', array( new Your_Class, 'init' ) );

// One time activation functions
register_activation_hook( PATH_TO_PLUGIN_FILE, array( new Your_Class, 'flush_rules' ) );
Matt Keys
la source
1
vous pouvez également simplement utiliser add_rewrite_endpoint, qui générera la règle pour vous et ajoutera la requête var en une seule fois. aussi si vous ajoutez vos propres règles de réécriture, je suggère la add_rewrite_rulefonction au lieu du filtrage rewrite_rules_array.
Milo
Merci Milo, j'ai mis à jour le code pour utiliser add_rewrite_rule au lieu de filtrer le tableau de réécriture. J'ai regardé add_rewrite_endpoint mais je pense que add_rewrite_tag peut être mieux adapté à mes besoins. Il semble que add_rewrite_endpoint soit surtout utile si vous souhaitez ajouter un argument supplémentaire aux réécritures WP existantes. Corrigez-moi si je me trompe ici.
Matt Keys
1
J'aime l'approche orientée objet. Trop de développeurs WP ne savent toujours pas comment utiliser la POO. Merci d'avoir essayé de restaurer ma foi dans les développeurs PHP. ;)
Arvid