Benutzerdefinierte Plugin-Route in Wordpress

12

Okay, meine Frage ist ganz einfach. Ich muss einige benutzerdefinierte Routing-Regeln für mein Plugin implementieren. Diese Routen würden nur ein Argument annehmen (also nichts Kompliziertes) und würden folgendermaßen aussehen: http://www.example.org/myroute/myargument

Im Idealfall wird dadurch eine benutzerdefinierte Klasse aufgerufen und eine benutzerdefinierte Vorlage angezeigt (die direkt auf die Klasse zugreifen kann).

Was ist der beste Ansatz dafür? Prost

Fran
quelle

Antworten:

15

Sie müssen drei wichtige Dinge tun:

  1. Erstellen Sie eine benutzerdefinierte Umschreiberegel, um Teile des URI in Werte umzuwandeln, an die übergeben wird index.php.
  2. In myrouteund myargumentauf Wordpress - Abfrage Variablen weiße Liste, so dass Wordpress nicht einfach ignorieren , wenn sie in einer Abfragezeichenfolge angezeigt.
  3. Löschen Sie die Umschreiberegeln.

Erstens werde ich empfehlen, dass http://www.example.org/myroute/myargumentSie sich stattdessen für ein spezielles Präfix oder Suffix entscheiden, um anzugeben, wann der URI als eine dieser speziellen "Routen" betrachtet werden soll. Für dieses Beispiel habe ich das Präfix apiso gewählt, dass es so ist http://www.example.org/api/myroute/myargument. Ich habe apimich für eine API entschieden, als ich etwas RESTful gemacht habe, wie das, woran Sie anscheinend arbeiten.

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

Schnelle Aufschlüsselung

Es ist alles ziemlich einfach. Das Regex-Muster wird einer Liste aller Umschreiberegeln in WordPress hinzugefügt, und Ihr benutzerdefiniertes Muster steht ganz oben auf der Liste. Wenn das Muster übereinstimmt, durchsucht WordPress die Liste der Umschreiberegeln nicht mehr und verwendet die erfassten Werte des regulären Ausdrucks anstelle der Referenzen ( $matches[1]und $matches[2]) in der an übergebenen Abfragezeichenfolge index.php.

Durch das Hinzufügen der Abfragevariablen myrouteund myargumentder Whitelist wird WordPress nur auf sie achten, anstatt sie zu verwerfen.

Alternative Methode zum "Namespace" Ihrer benutzerdefinierten Route

Wenn Sie die Verwendung /api/als Präfix vermeiden möchten, können Sie stattdessen eine Abfragezeichenfolgenvariable / ein Abfragezeichenfolgenfeld verwenden. Um so etwas zu tun, würden Sie den regulären Ausdruck in etwas Ähnliches ändern (.*?)/(.+?)\\?api=1und dann apials zusätzlichen Parameter zum array_push()Aufruf von hinzufügen my_insert_query_vars().

Das würde die benutzerdefinierte Route so ändern, dass sie jederzeit api=1ausgelöst wird http://example.com/anytext/anytext?api=1. Dies ist das erste Element der Abfragezeichenfolge, z. B. für .

Ignorieren Sie die Verwendung des Begriffs "Namespace" - verwenden Sie ihn nur der Kürze halber.

Wenn Sie keinen 'Namespace' mit einem Präfix oder einem Suffix haben, werden Sie mit kollidierenden URI-Mustern enden. Dies liegt daran, dass WordPress Ihr benutzerdefiniertes Muster nicht von einem Muster unterscheiden kann, das als Beitrag oder Seite gedacht ist. Wie würde WordPress wissen, dass dies myroutekeine Taxonomie, kein Begriff oder keine übergeordnete Seite ist?

Hoffe das hilft.

eddiemoya
quelle
1
Praktischer Hinweis: Regeln werden in my_insert_rewrite_rulesder Reihenfolge der Definition definiert! Beginnen Sie zuerst mit der längsten Regel und arbeiten Sie dann bis zur einfachsten, andernfalls überschreibt / api / myroute / api / myroute / myargument.
emc
1
@npc Dies ist ein wichtiger Punkt, den Sie beim Erstellen von benutzerdefinierten Umschreiberegeln beachten sollten. Sie können auch auf diese Weise kollidieren. Im obigen Beispiel ist dies jedoch kein Problem, da / api / myroute einfach kein gültiger Pfad wäre.
Eddiemoya
Wie kann jemand eine benutzerdefinierte Vorlage aus seinem Plugin-Verzeichnis laden, wenn die Seite example.org/api/myroute/myargument angefordert wurde?
Matt Keys
1
Hier ist die aktuelle und vollständige Lösung von WordPress: codex.wordpress.org/Rewrite_API/add_rewrite_rule
Imran Zahoor
5

Um etwas näher auf das einzugehen, was eddiemoya oben getan hat:

Wie das Originalposter dieser Frage wollte ich ein benutzerdefiniertes Umschreiben erstellen und auch eine benutzerdefinierte Vorlage für diese Umschreibeseite bereitstellen. Mit dem Code von edditmoya habe ich in die richtige Richtung gestartet und eine zusätzliche Funktion hinzugefügt, um meine benutzerdefinierte Vorlage beim Zugriff auf die Seite bereitzustellen.

Die benutzerdefinierte Vorlage kann sich überall befinden, in meinem Fall ist sie im Plugin-Verzeichnis gespeichert.

Ich wollte auch nur überprüfen, ob die Umschreiberegeln während der Plugin-Aktivierung gelöscht werden mussten, also habe ich das auf einen register_activation_hook gesetzt

Unten finden Sie ein vollständiges Beispiel für das, was ich getan habe:

AKTUALISIERT vereinfacht auf Empfehlung von 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
quelle
1
Sie können auch einfach verwenden add_rewrite_endpoint, wodurch die Regel für Sie generiert und die Abfragevariable auf einmal hinzugefügt wird. Auch wenn Sie Ihre eigenen Umschreiberegeln hinzufügen, empfehle ich die add_rewrite_ruleFunktion anstelle der Filterung rewrite_rules_array.
Milo
Dank Milo habe ich den Code aktualisiert, um add_rewrite_rule zu verwenden, anstatt das Rewrite-Array zu filtern. Ich habe mir add_rewrite_endpoint angesehen, aber ich denke, add_rewrite_tag passt möglicherweise besser zu meinen Anforderungen. Es scheint, dass add_rewrite_endpoint meistens nützlich ist, wenn Sie vorhandenen WP-Umschreibungen zusätzliche Argumente hinzufügen möchten. Korrigieren Sie mich, wenn ich hier falsch liege.
Matt Keys
1
Ich mag den objektorientierten Ansatz. Zu viele WP-Entwickler wissen immer noch nicht, wie sie OOP verwenden sollen. Vielen Dank, dass Sie versucht haben, mein Vertrauen in PHP-Entwickler wiederherzustellen. ;)
Arvid