URLs do WordPress sem postagens

3

Estamos trabalhando em um sistema maior, que é baseado no WordPress, mas o WordPress é usado apenas para conteúdo "estático", a parte principal do sistema deve consumir a API externa e exibir os dados.

Meu ponto é: eu sou capaz de dizer a reescrita de URL para não usar o sistema interno do WordPress para algumas URLs e usar outra coisa?

Por exemplo mysite.com/news/news-title mostraria a postagem, mas mysite.com/customcontent/anotherlink chamaria algum mecanismo para carregar dados da API e exibi-la.

Eu não sei se isso é possível com o WordPress. Obrigado por seus pontos.

    
por Karel Attl 11.08.2014 / 15:41

1 resposta

9

Sim, é possível.

O fluxo de trabalho de interface do WordPress pode ser resumido da seguinte forma:

  1. Uma URL é visitada
  2. Ao verificar o URL atual em relação a todos os padrões e regras de regravação personalizadas , o URL é "convertido" em um conjunto de argumentos para < href="http://codex.wordpress.org/Class_Reference/WP_Query"> WP_Query . Isso é feito pelo método parse_request de uma instância da classe WP armazenada na variável global $wp
  3. Uma instância de WP_Query (salva na variável global $wp_query ) é usada para consultar o banco de dados e obter as postagens relacionadas aos argumentos recuperados no ponto # 2. Isso é referenciado como "consulta principal"
  4. Com base nos argumentos da consulta, um modelo é escolhido de acordo com a hierarquia de modelos e é carregado e usado para exibir os resultados

Assim, mesmo se você registrar um conjunto de regras de regravação personalizadas, elas serão usadas para consultar postagens.

No entanto, se você olhar para a fonte do método parse_request , nas primeiras linhas você vê isso:

if ( ! apply_filters( 'do_parse_request', true, $this, $extra_query_vars ) )
  return;

Portanto, atribuindo um retorno de chamada ao filtro 'do_parse_request', você poderá interromper o processo de análise do WordPress e fazer o que precisar.

Existem maneiras diferentes de fazer essa tarefa, aqui para simplificar, vou dar um exemplo aproximado.

Como dito, precisamos fazer uma correspondência de URL personalizada para ... algo , provavelmente um retorno de chamada que recupera alguns dados e uma visualização para exibi-los.

Para tornar o código reutilizável, podemos usar uma classe que aceita configurações de URL personalizadas por meio de um filtro e usar essas configurações de URL personalizadas para mostrar o que precisamos, usando um retorno de chamada para obter alguns dados e exibi-los.

class MyCustomUrlParser {

  private $matched = array();

  /**
   * Run a filter to obtain some custom url settings, compare them to the current url
   * and if a match is found the custom callback is fired, the custom view is loaded
   * and request is stopped.
   * Must run on 'do_parse_request' filter hook.
   */
  public function parse( $result ) {
    if ( current_filter() !== 'do_parse_request' ) {
      return $result;
    }
    $custom_urls = (array) apply_filters( 'my_custom_urls', array() );
    if ( $this->match( $custom_urls ) && $this->run() ) {
      exit(); // stop WordPress workflow
    }
    return $result;
  }

  private function match( Array $urls = array() ) {
    if ( empty( $urls ) ) {
      return FALSE;
    }
    $current = $this->getCurrentUrl();
    $this->matched = array_key_exists( $current, $urls ) ? $urls[$current] : FALSE;
    return ! empty( $this->matched );
  }

  private function run() {
    if (
      is_array( $this->matched )
      && isset( $this->matched['callback'] )
      && is_callable( $this->matched['callback'] )
      && isset( $this->matched['view'] )
      && is_readable( $this->matched['view'] )
    ) {
      $GLOBALS['wp']->send_headers();
      $data = call_user_func( $this->matched['callback'] );
      require_once $this->matched['view'];
      return TRUE;
    }
  }

  private function getCurrentUrl() {
    $home_path = rtrim( parse_url( home_url(), PHP_URL_PATH ), '/' );
    $path = rtrim( substr( add_query_arg( array() ), strlen( $home_path ) ), '/' );
    return ( $path === '' ) ? '/' : $path;
  }

}

Essa é uma classe aproximada que permite que os usuários definam configurações de URL personalizadas por meio de um filtro ('my_custom_urls'). As configurações de URL personalizadas devem ser uma matriz em que as chaves são URLs relativas e cada valor é uma matriz contendo dois valores-chave: um com a chave "callback" e outro com a chave "view".

O retorno de chamada é uma chamada (qualquer coisa para a qual is_callable retorna verdadeiro) e view é um arquivo usado para renderizar os dados retornados pelo callable e acessíveis no arquivo de visualização na variável $data .

Veja um exemplo de como usar a classe.

// first of all let's set custom url settings
add_filter( 'my_custom_urls', 'set_my_urls' );

function set_my_urls( $urls = array() ) {
  $my_urls = array(
     '/customcontent/alink' => array(
       'callback' => 'my_first_content_callback',
       'view'     => get_template_directory() . '/views/my_first_view.php'
     ),
     '/customcontent/anotherlink' => array(
       'callback' => 'my_second_content_callback',
       'view'     => get_template_directory() . '/views/my_second_view.php'
     )
  );
  return array_merge( (array) $urls, $my_urls ); 
}

// require the file that contain the MyCustomUrlParser class
require '/path/to/MyCustomUrlParser';

// attach MyCustomUrlParser::parse() method to 'do_parse_request' filter hook
add_filter( 'do_parse_request', array( new MyCustomUrlParser, 'parse' ) );

É claro que precisamos escrever my_first_content_callback e my_second_content_callback e também my_first_view.php e my_second_view.php .

Como exemplo, o retorno de chamada seria algo assim:

function my_first_content_callback() {
  $content = get_transient( 'my_first_content' );
  if ( empty( $content ) ) {
     $api = a_method_to_get_an_external_api_object();
     $json = $api->fetch_some_json_data();
     $content = json_decode( $json );
     // cache content for 1 hour
     set_transient( 'my_first_content', $content, HOUR_IN_SECONDS );
  }
  return $content;
}

Observe que qualquer retorno de chamada é armazenado na variável $data acessível na exibição. Em fatos, um arquivo de visualização seria algo assim:

<?php get_header(); ?>

<h1>My Content from API</h1>

<div>
   <pre><?php print_r( $data ); ?></pre>
</div>

<?php get_footer() ?>

Isso funciona e é bastante reutilizável. Você pode definir todos os URLs personalizados que quiser usando o filtro 'my_custom_urls' .

No entanto, existe uma desvantagem: toda a correspondência com o URL atual é feita por meio de uma correspondência exata , mas usando um sistema de correspondência regex seria muito melhor para projetos grandes porque você pode usar o URLs para passar algumas variáveis para callbacks.

Por exemplo se você tiver uma configuração de URL como esta:

'/customcontent/alink/page/{page}' => array(
   'callback' => 'my_first_content_callback',
   'view'     => get_template_directory() . '/views/my_first_view.php'
) 

usando um sistema regex é possível fazer a variável {page} part e o valor correspondente pode ser passado para o retorno de chamada para recuperar dados diferentes.

Isso é o que é comumente chamado de sistema de roteamento , e há algumas bibliotecas PHP úteis, como FastRoute , Pux e Componente de Roteamento do Symfony que pode ajudá-lo a usar o fluxo de trabalho que eu expliquei aqui e construir seu próprio sistema de roteamento baseado em regex no WordPress.

Se você tem o PHP 5.4+ (que é realmente recomendado), existe um plugin que eu escrevi chamado Cortex que implementa o Symfony Routing Component e o torna utilizável no WordPress tanto para consultas padrão do WordPress (mostrando postagens) quanto para conteúdo personalizado como você precisa.

    
por gmazzap 11.08.2014 / 18:05