Determine los parámetros WP_Query a partir de la URL

2

Me pregunto si es posible determinar los parámetros de WP_Query mediante solo utilizando la URL de la página dada. La razón por la que estoy tratando de hacer esto es porque estoy desarrollando un tema de SPA (y, en última instancia, una respuesta JSON) y necesitaré poder determinar una consulta sin volver a cargar la página.

Pensé que es bastante intrépido, he logrado vincular una URL de publicación con la estructura de Permalink para determinar qué debe ser una única consulta de publicación:

<?php

function api_query_url() {

  // Check that the URL is set and is in fact a string
  if ( ! isset( $_POST['url'] ) || gettype( $_POST['url'] ) !== 'string' ) {
    api_response( false, 400, "'url' is a required parameter!" );
  }

  // Parse the URL for parameters and path
  $query_url = parse_url( $_POST['url'] );

  // Pass query-based URL directly to Single API request
  if ( isset( $query_url['query'] ) ) {
    api_single( $query_url['query'] );
  }

  // Map Permalink structure tags to WP_Query parameters
  $structure_refs = array(
    'year'     => 'year',
    'monthnum' => 'monthnum',
    'day'      => 'day',
    'hour'     => 'hour',
    'minute'   => 'minute',
    'second'   => 'second',
    'post_id'  => 'p',
    'postname' => 'name',
    'category' => 'category_name',
    'author'   => 'author_name'
  );

  // Retreive the site's Permalink Structure and break it in to an array
  $structure = array_filter( explode( '/', get_option( 'permalink_structure' ) ) );

  // Break our query parameters in to an array
  $query_params = array_filter( explode( '/', $query_url['path'] ) );

  // Set up an empty query array
  $query = array();

  // For each query parameter received
  foreach ($query_params as $param) {

    // Using the parameter value's position, locate its corresponding structure key
    $key_position  = array_search( $param, $query_params );
    $structure_key = str_replace( '%', '', $structure[$key_position] );

    // If the structure key exists in the structure references, add to to the query
    if ( array_key_exists( $structure_key, $structure_refs) ) {
      $query[$structure_refs[$structure_key]] = $param;
    }
  }

  // Pass off to Query handler to create JSON response
  api_single( $query );

}
add_action( 'wp_ajax_nopriv_api_query_url', 'api_query_url' );

Al utilizar la función anterior, puedo pasarle a url como parámetro para realizar una llamada ajax, y la analizará para encontrar los parámetros de WP_Query.

Por lo tanto, se analizará una URL como http://example.com/blog/my-first-post/ para extraer name => 'my-first-post' y una URL como http://example.com/?p=124 se analizará para extraer p => 124 . Esto luego pasa a un WP_Query y así sucesivamente. FTR, también elimino cualquier parámetro de la lista negra, como post_status o has_password en un intento de mantener las cosas seguras.

Para analizar una bonita estructura de URL, tomo los componentes de la ruta, así que para /2014/07/hello-world/ obtenemos 2014 , 07 y hello- world , y luego los comparo con la estructura establecida de permalink, que en este caso sería /%year%/%monthnum%/%postname%/ , y como algunas etiquetas de permalink no funcionan con WP_Query, hago algunas conversiones; por ejemplo, postname sería name .

De todos modos ... sentí que tenía un buen comienzo, hasta que llegué a las páginas. Con mi código anterior, una URL de página como http://example.com/about/ y la estructura de enlace permanente anterior, los parámetros extraídos serían year => 'about' . No es bueno.

Si alguien tiene alguna orientación sobre cómo debo abordar esto, se apreciaría mucho . También, por favor, avíseme si me estoy acercando a todo esto mal. Solo necesito determinar una consulta sin volver a cargar la página.

    
pregunta Jody Heavener 14.07.2014 - 21:45

2 respuestas

5

Editado en julio de 2014 a las 6:28

Hay muchos errores con tu enfoque. No funcionará si hay alguna regla de reescritura personalizada, (probablemente) no funcionará si el servidor es IIS y si el enlace permanente está activo, no funcionará para tipos de publicaciones personalizados, no funcionará para archivar o buscar URL, etc. .

Para obtener una URL de publicación / página de una URL de una manera asequible, existe la función url_to_postid , por ejemplo,

$id = url_to_postid( $query_url['path'] );

if ( is_numeric( $id ) && (int) $id > 0 ) {
  // the required post id is: $id
} else {
  // the url is not for a single post, may be an archive url, a search url or even
  // a non-valid 404 url
}

Si solo te interesa la publicación única (incluso CPT) o las URL de página, probablemente las pocas líneas de arriba sean lo único que necesitas, pero si necesitas analizar todo tipo de URL de WordPress, entonces necesitas algo más, Y no es algo realmente fácil.

La única forma de obtener vars de consulta de una url de manera asequible, es reproducir la forma en que WordPress utiliza para analizar una url.

Esto se realiza en el núcleo mediante el método parse_request de la clase WP .

Sin embargo, usar ese método para nuestro propósito explicado anteriormente es difícil / desalentador porque:

  • accede directamente a las variables $_SERVER , $_POST y $_GET , lo que dificulta el análisis de direcciones URL arbitrarias no relacionadas con la solicitud HTTP actual
  • desencadena algunos enlaces de acción estrictamente relacionados con el análisis de la solicitud HTTP actual, lo que no tiene sentido activar para urls arbitrarias
  • accede y modifica las propiedades de la variable global $wp que no debe cambiarse después de analizar la solicitud o es muy probable que las cosas se rompan.

Lo que podemos hacer es comenzar desde el código allí, eliminar las partes que no necesitamos y hacer que el código use una URL arbitraria en lugar de la de la solicitud HTTP actual.

El método

Core parse_request tiene 214 líneas de largo (v. 3.9.1) y hacer ese trabajo puede ser una molestia, pero afortunadamente alguien ya ha hecho el trabajo duro, vea aquí .

    
respondido por el gmazzap 15.07.2014 - 00:05
1

Hay una solución simple que utiliza un mecanismo bueno y otro extraño.

La parte buena

function api_query_url()
{
  // Check that the URL is set and is in fact a string
  if ( ! isset( $_POST['url'] ) || gettype( $_POST['url'] ) !== 'string' ) {
    api_response( false, 400, "'url' is a required parameter!" );
  }

  // Add an extra parameter to the url.
  $api_url = add_query_arg( 'json_vars', time(), $_POST['url'] );

  $request = wp_remote_request( $api_url );
  $content = wp_remote_retrieve_body( $request );

  if( is_wp_error($content) ){
    api_response( false, 400, "couldn't retrive the data" );
  }

  if( !empty($content) )
      $vars = json_decode( $content );
  else
      $vars = array();

  // pass the array to your function
  api_single( $vars );
}
add_action( 'wp_ajax_nopriv_api_query_url', 'api_query_url' );  

La parte impar

/* Comparing the extra parameter (json_vars), we return the json of the vars & no html */
function api_parse_request( $q )
{
    /* home/front-page doesn't have any q-vars */
    /* so you might be setting some defaults for that */
    $vars = $q->query_vars;
    if( isset($_REQUEST['json_vars']) ){
        echo json_encode( $vars );
        die();
    }
}
add_action( 'parse_request', 'api_parse_request' );
    
respondido por el Shazzad 14.07.2014 - 22:41

Lea otras preguntas en las etiquetas