Rota do plugin personalizado no Wordpress

12

Ok, então minha pergunta é bem simples. Preciso implementar algumas regras de roteamento personalizadas para o meu plug-in. Essas rotas levariam apenas um argumento (portanto, nada complicado) e teriam a seguinte aparência: http://www.example.org/myroute/myargument

E, idealmente, isso chamaria uma classe personalizada e exibia um modelo personalizado (que poderia acessar diretamente a classe).

Qual é a melhor abordagem para isso? Felicidades

Fran
fonte

Respostas:

15

Você precisa fazer três coisas importantes:

  1. Crie uma regra de reescrita personalizada para transformar partes do URI em valores passados index.php.
  2. Adicione myroutee myargumentà lista de permissões de variáveis ​​de consulta do WordPress, para que o WordPress não as ignore apenas quando elas aparecerem em uma sequência de consultas.
  3. Liberar as regras de reescrita.

Primeiramente, vou recomendar que, em vez de http://www.example.org/myroute/myargument, você opte por algum tipo de prefixo ou sufixo especial para indicar quando o URI deve ser considerado uma dessas 'rotas' especiais. Para o bem deste exemplo, eu escolhi o prefixo api, de modo que seria http://www.example.org/api/myroute/myargument. Eu escolhi apiporque quando fiz algo RESTful, como o que você parece estar trabalhando, foi para uma API.

O 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() 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;
}

Avaria Rápida

É tudo bastante direto. O padrão regex é adicionado a uma lista de todas as regras de reescrita no WordPress e seu padrão personalizado está no topo da lista. Quando o padrão for correspondido, o WordPress deixará de examinar a lista de regras de reescrita e usará os valores capturados da regex no lugar das referências ( $matches[1]e $matches[2]) na cadeia de consulta passada para index.php.

Adicionar as variáveis ​​de consulta myroutee myargumenta lista de permissões apenas faz o WordPress prestar atenção nelas, em vez de descartá-las.

Maneira alternativa de 'namespacing' sua rota personalizada

Se você quiser evitar o uso /api/como prefixo, poderá usar uma variável / campo de seqüência de caracteres de consulta. Para fazer algo assim, você alteraria o regex para algo assim (.*?)/(.+?)\\?api=1e, em seguida, adicionaria apicomo um parâmetro adicional à array_push()chamada efetuada my_insert_query_vars().

Isso mudaria a rota personalizada para que seja acionada a qualquer momento, api=1seja o primeiro elemento da string de consulta, por exemplo, seria acionada http://example.com/anytext/anytext?api=1.

Ignore o uso do termo 'namespacing' - apenas use-o por questões de brevidade.

Se você não 'namespace' com prefixo ou sufixo, você acabará colidindo com os padrões de URI. Isso ocorre porque o WordPress não tem como distinguir seu padrão personalizado de um post ou página. Como o WordPress saberia que myroutenão é uma taxonomia, termo ou página pai?

Espero que isto ajude.

eddiemoya
fonte
1
Nota prática: regras definidas na my_insert_rewrite_rulesordem de definição a seguir! Comece com a regra mais longa primeiro e depois trabalhe com a mais simples, caso contrário / api / myroute substituirá / api / myroute / myargument.
emc
1
@npc Esse é um ponto importante a ser observado ao criar regras de reescrita personalizadas; elas também podem colidir dessa maneira. No exemplo acima, porém, isso não é um problema, porque / api / myroute simplesmente não seria um caminho válido.
precisa saber é
Como alguém carregava um modelo personalizado a partir do diretório de plugins, sempre que a página example.org/api/myroute/myargument era solicitada?
Matt chaves
1
Aqui está a solução real e completa pelo wordpress: codex.wordpress.org/Rewrite_API/add_rewrite_rule
Imran Zahoor
6

Para expandir um pouco o que eddiemoya fez acima:

Como o pôster original desta pergunta, eu queria criar uma reescrita personalizada e também fornecer um modelo personalizado para essa página de reescrita. O código de edditmoya me levou a começar na direção certa e adicionei uma função extra para servir meu modelo personalizado quando a página é acessada.

O modelo personalizado pode estar localizado em qualquer lugar, no meu caso, é armazenado no diretório do plugin.

Eu também só queria verificar se as regras de reescrita precisavam ser liberadas durante a ativação do plug-in, então coloquei isso em um register_activation_hook

Veja abaixo o exemplo completo do que fiz:

ATUALIZADO simplificado com base nos conselhos da 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
fonte
1
você também pode usar add_rewrite_endpoint, o que irá gerar a regra para você e adicionar a consulta var de uma só vez. Além disso, se você estiver adicionando suas próprias regras de reescrita, sugiro a add_rewrite_rulefunção em vez de filtrar rewrite_rules_array.
Milo
Obrigado Milo, atualizei o código para usar add_rewrite_rule em vez de filtrar a matriz de reescrita. Eu olhei para add_rewrite_endpoint, mas acho que add_rewrite_tag pode ser mais adequado às minhas necessidades. Parece que add_rewrite_endpoint é útil principalmente se você deseja adicionar um argumento extra às reescritas existentes do WP. Corrija-me se eu estiver errado aqui.
Matt Keys
1
Eu gosto da abordagem orientada a objetos. Muitos desenvolvedores de WP ainda não sabem como usar o OOP. Obrigado por tentar restaurar minha fé em desenvolvedores de PHP. ;)
Arvid