Tipo de publicación personalizada como página principal

4

Por lo tanto, hay un millón de fragmentos de cómo obtener páginas como padres de tipos de publicación personalizados.

Sin embargo, lo contrario parece ser cuestionable. Uno podría pensar, ya que todo en WordPress es técnicamente un "post", esto sería trivial. Sin embargo, no lo es.

Hasta ahora, tengo:

add_filter( 'page_attributes_dropdown_pages_args',
  function( $dropdown_args, $post = null ) {
    $dropdown_args['post_type'] = 'portal';
    return $dropdown_args;
  } );

Y, efectivamente, las páginas ahora me permiten seleccionar portal -type posts como padres. Parece que las URL se registran correctamente dentro de WordPress, aunque todas son 404.

¿Cómo puedo hacer que wordpress comprenda esta jerarquía y cargue las páginas que tienen publicaciones como padres?

    
pregunta Qix 26.01.2015 - 07:27

3 respuestas

6

WordPress usa un conjunto de reglas de reescritura para poder convertir una URL en una consulta de base de datos.

La expresión regular que maneja las URL de las páginas es muy general, IIRC es algo así como (.+.?)/? , matemáticamente, prácticamente todo no ha sido compatible con otras reglas.

Por esta razón, no es posible escribir una regla de reescritura que funcione en su caso: porque no puede distinguir a través de expresiones regulares que en una URL como example.com/my-portal/sample-page la parte 'my-portal' es un CPT y sample-page es una página.

Las cosas se vuelven más complejas si tiene más niveles de anidación: my-portal/my-portal-child/sample-page .

Para manejar este tipo de urls, WordPress usa la función get_page_by_path() : explota la url de la página / , obteniendo barras de página, luego consulta la base de datos de todas las páginas que tienen esas barras.

Por ejemplo, si tienes una página cuyo slug es "sample-page" y configuras como principal el CPT "my-portal" WordPress calls:

get_page_by_path('my-portal/sample-page')

pero no devuelve ningún resultado porque busca una página con el slug 'muestra de página' cuyo padre es otra página con el slug 'my-portal' . Esa página no existe, por lo que aparece el error 404.

Sin embargo, get_page_by_path() acepta como tercer argumento una matriz de tipos de publicaciones: si lo configuras como array('page', 'portal') entonces la función podrá encontrar la página correctamente.

Por lo tanto, puede resolver el problema configurando manualmente la identificación de la página (recuperada como se explicó anteriormente) en las ventanas de consulta WP.

El gancho 'parse_request' es perfecto para el alcance:

  • se ejecuta después de que se haya analizado la url
  • pasa a enlazar devoluciones de llamada la instancia del objeto $wp que puede usar para establecer las variables de consulta

Código:

add_action('parse_request', function ($wp) {
  // only if WP found a page
  if (isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
    $page = get_page_by_path( // let's find the page object
        $wp->query_vars['pagename'],
        OBJECT,
        array('page', 'portal') // we need to set both post types
    );
    if ($page instanceof WP_Post) { // if we find a page
        unset($wp->query_vars['pagename']); // remove pagename var
        $wp->query_vars['page_id'] = $page->ID; // replace with page_id query var
    }
  }
});

Este código, en combinación con el filtro en OP, es todo lo que necesita.

Tenga en cuenta que el código funciona incluso con portales jerárquicos anidados.

    
respondido por el gmazzap 29.01.2015 - 08:13
0

Entonces, la respuesta de @ gmazzap era un punto en la dirección correcta. Sin embargo, por la razón que sea, var_dump($wp->query_vars) solo mostraba una matriz con una clave, attachment , que no ayudó en absoluto.

Sin embargo, mostró cómo podría lograr esto usando un poco más de trucos.

La siguiente secuencia de comandos obtiene una página solo si la jerarquía es correcta; es decir, el padre de cada babosa hace coincidir una publicación con la babosa apropiada (por supuesto, 0 para la primera babosa).

Además, omite las rutas con 0 o 1 slugs simplemente porque esas generalmente significan páginas especiales que WordPress debería manejar (además, en realidad no importa en términos de jerarquía de páginas ...)

Y no, la consulta no se puede optimizar demasiado. Esto se debe al hecho de que MySQL no admite selecciones / uniones recursivas como desearía en un modelo de datos jerárquico.

function get_page_by_slug_path( $path ) {
  global $wpdb;
  global $table_prefix;

  $slugs = explode(
    '/',
    preg_replace(
      '~\/+~',
      '/',
      preg_replace(
        '~^\/*(.+?)\/*$~',
        '$1',
        $path
      )
    )
  );

  # Skip if slugs length is 1 or 0, of course.
  #   A single 'slug' URL may mean something completely different, so
  #   we'll bank on WordPress knowing what to do with it.
  if( count( $slugs ) < 2 ) {
    return;
  }

  $parents = [ 0 ];
  foreach( $slugs as $slug ) {
    $sql = $wpdb->prepare(
      "SELECT ID FROM ${table_prefix}posts WHERE post_name='%s' AND post_parent IN ("
      . implode( ',', $parents )
      . ")",
      $slug
    );

    $results = $wpdb->get_results( $sql );

    if( count( $results ) === 0 ) {
      return null;
    }

    $parents = array_map(
      function( $elem ) {
        return $elem->ID;
      },
      $results
    );

  }

  if( count( $parents ) > 1 ) {
    trigger_error( E_USER_WARNING, "Multiple IDs for this page slug: "
      . implode( ', ', $parents ) );
  }

  return intval( $parents[0] );
}

add_action('parse_request', function ($wp) {
  $path = parse_url(
    "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
    PHP_URL_PATH
  );

  $pageID = get_page_by_slug_path( $path );

  if( $pageID ) {
    $wp->query_vars = [ 'page_id' => $pageID ];
  }
});
    
respondido por el Qix 03.02.2015 - 04:58
-1
  add_action('admin_menu', function() { remove_meta_box('pageparentdiv', 'chapter', 'normal');});
  add_action('add_meta_boxes', function() { add_meta_box('chapter-parent', 'Part', 'chapter_attributes_meta_box', 'chapter', 'side', 'high');});
  function chapter_attributes_meta_box($post) {
    $post_type_object = get_post_type_object($post->post_type);
    if ( $post_type_object->hierarchical ) {
      $pages = wp_dropdown_pages(array('post_type' => 'part', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
      if ( ! empty($pages) ) {
        echo $pages;
      } // end empty pages check
    } // end hierarchical check.
  }

Intente esta respuesta en: enlace

    
respondido por el TTech IT Solutions 26.01.2015 - 10:29

Lea otras preguntas en las etiquetas