Ruta personalizada de plugin en WordPress

10 jul 2012, 22:14:25
Vistas: 23K
Votos: 16

Bien, mi pregunta es bastante simple. Necesito implementar algunas reglas de enrutamiento personalizadas para mi plugin. Estas rutas solo tomarían un argumento (nada complicado) y se verían así: http://www.example.org/myroute/myargument

Y lo ideal sería que esto llamara a una clase personalizada y mostrara una plantilla personalizada (que pudiera acceder directamente a la clase).

¿Cuál es el mejor enfoque para esto? Gracias

0
Todas las respuestas a la pregunta 2
4
16

Necesitas hacer tres cosas importantes:

  1. Crear una regla de reescritura personalizada para convertir partes del URI en valores pasados a index.php.
  2. Añadir myroute y myargument a la lista blanca de variables de consulta de WordPress, para que WordPress no las ignore cuando aparezcan en una cadena de consulta.
  3. Vaciar las reglas de reescritura.

En primer lugar, voy a recomendar que en lugar de http://www.example.org/myroute/myargument, utilices algún tipo de prefijo o sufijo especial para denotar cuándo el URI debe considerarse una de estas "rutas" especiales. Para este ejemplo, he elegido el prefijo api, por lo que sería http://www.example.org/api/myroute/myargument. Elegí api porque cuando hice algo RESTful, como lo que pareces estar trabajando, era para una API.

El Código

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() si nuestras reglas aún no están incluidas
function my_flush_rules() {
    $rules = get_option( 'rewrite_rules' );

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

// Añadiendo una nueva regla
function my_insert_rewrite_rules( $rules ) {
    $newrules = array();
    $newrules['api/(.*?)/(.+?)'] = 'index.php?myroute=$matches[1]&myargument=$matches[2]';
    return $newrules + $rules;
}

// Añadiendo la variable id para que WordPress la reconozca
function my_insert_query_vars( $vars ) {
    array_push( $vars, 'myroute', 'myargument' );
    return $vars;
}

Desglose rápido

Es bastante sencillo. El patrón regex se añade a una lista de todas las reglas de reescritura en WordPress, y tu patrón personalizado está en la parte superior de la lista. Cuando el patrón coincide, WordPress dejará de buscar en la lista de reglas de reescritura y usará los valores capturados por el regex en lugar de las referencias ($matches[1] y $matches[2]) en la cadena de consulta pasada a index.php.

Añadir las variables de consulta myroute y myargument a la lista blanca hace que WordPress les preste atención en lugar de descartarlas.

Forma alternativa de 'agrupar' tu ruta personalizada

Si quisieras evitar usar /api/ como prefijo, podrías usar una variable/campo de cadena de consulta en su lugar. Para hacer algo así, cambiarías el regex a algo como (.*?)/(.+?)\\?api=1 y luego añadirías api como un parámetro adicional a la llamada array_push() hecha en my_insert_query_vars().

Eso cambiaría la ruta personalizada para que se active cada vez que api=1 sea el primer elemento de la cadena de consulta, por ejemplo, se activaría para http://example.com/anytext/anytext?api=1.

Ignora el uso del término 'agrupar' - solo lo usé por brevedad.

Si no 'agrupas' con un prefijo o un sufijo, terminarás con patrones de URI que colisionan. Esto se debe a que WordPress no tendrá forma de distinguir tu patrón personalizado de uno destinado a ser una entrada o página. ¿Cómo sabría WordPress que myroute no es una taxonomía, término o una página padre?

Espero que esto ayude.

11 jul 2012 03:28:19
Comentarios

Nota útil: las reglas definidas en my_insert_rewrite_rules siguen el orden de definición. ¡Comienza con la regla más larga primero y luego baja a la más simple, de lo contrario /api/miruta anulará /api/miruta/miargumento.

emc emc
25 feb 2014 19:42:52

@npc Ese es un punto importante a tener en cuenta al crear reglas de reescritura personalizadas, también pueden colisionar de esa manera. En el ejemplo anterior, sin embargo, eso no es un problema porque /api/miruta simplemente no sería una ruta válida.

eddiemoya eddiemoya
3 mar 2014 21:37:13

¿Cómo podría alguien cargar una plantilla personalizada desde su directorio de plugins cada vez que se solicite la página http://www.example.org/api/miruta/miargumento?

Matt Keys Matt Keys
21 sept 2014 13:36:17

Aquí está la solución actual y completa de WordPress: https://codex.wordpress.org/Rewrite_API/add_rewrite_rule

Imran Zahoor Imran Zahoor
12 sept 2015 23:15:56
3

Para ampliar un poco lo que hizo eddiemoya anteriormente:

Al igual que el autor original de esta pregunta, quería crear una reescritura personalizada y también entregar una plantilla personalizada para esa página reescrita. El código de edditmoya me puso en el camino correcto, y agregué una función adicional para servir mi plantilla personalizada cuando se accede a la página.

La plantilla personalizada podría estar en cualquier lugar, en mi caso está almacenada en el directorio del plugin.

También solo quería verificar si era necesario actualizar las reglas de reescritura durante la activación del plugin, así que lo coloqué en un register_activation_hook.

Mira a continuación el ejemplo completo de lo que hice:

ACTUALIZADO simplificado basado en el consejo 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 )
    {
        //intentar obtener la variable de consulta que registramos en nuestra función query_vars()
        $account_page = get_query_var( 'account_page' );

        //si la variable de consulta tiene datos, debemos estar en la página correcta, cargar nuestra plantilla personalizada
        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' ) );

// Funciones de activación únicas
register_activation_hook( PATH_TO_PLUGIN_FILE, array( new Your_Class, 'flush_rules' ) );
24 sept 2014 02:14:05
Comentarios

también puedes usar simplemente add_rewrite_endpoint, que generará la regla por ti y añadirá la variable de consulta de una sola vez. Además, si estás añadiendo tus propias reglas de reescritura, sugiero la función add_rewrite_rule en lugar de filtrar rewrite_rules_array.

Milo Milo
24 sept 2014 02:31:05

Gracias Milo, actualicé el código para usar add_rewrite_rule en lugar de filtrar el array de reescritura. Miré add_rewrite_endpoint pero creo que add_rewrite_tag podría adaptarse mejor a mis necesidades. Parece que add_rewrite_endpoint es principalmente útil si quieres añadir argumentos extra a las reescrituras existentes de WP. Corrígeme si estoy equivocado.

Matt Keys Matt Keys
24 sept 2014 03:03:30

Me gusta el enfoque orientado a objetos. Demasiados desarrolladores de WP todavía no saben cómo usar POO. Gracias por intentar restaurar mi fe en los desarrolladores PHP. ;)

Arvid Arvid
19 feb 2018 19:36:36