Tipo de postagem personalizada como pai da página

4

Portanto, há milhões de snippets para saber como obter páginas como pais de tipos de postagem personalizados.

No entanto, o inverso parece ser questionável. Alguém poderia pensar, uma vez que tudo no WordPress é tecnicamente um "post", isso seria trivial. No entanto, não é.

Até agora eu tenho:

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

E, com certeza, as páginas agora permitem que eu selecione as postagens portal -ty como pais. As URLs parecem se registrar corretamente no wordpress, apesar de todas elas serem 404.

Como posso obter o wordpress para entender essa hierarquia e carregar as páginas que têm postagens como pais?

    
por Qix 26.01.2015 / 07:27

3 respostas

6

O WordPress usa um conjunto de regras de reescrita para converter um URL em uma consulta ao banco de dados.

O regex que manipula urls para páginas é muito geral, o IIRC é algo como (.+.?)/? , ele mathes praticamente tudo já não foi correspondido por outras regras.

Por este motivo não é possível escrever uma regra de reescrita que funcione no seu caso: porque você não pode distinguir via regex que em um URL como example.com/my-portal/sample-page a parte 'meu-portal' é um CPT e sample-page é uma página.

As coisas ficam mais complexas se você tiver mais níveis de aninhamento: my-portal/my-portal-child/sample-page .

Para lidar com esse tipo de URL, o WordPress usa a função get_page_by_path() : ele explode o URL da página por / , obtendo slugs de página e, em seguida, consulta o banco de dados de todas as páginas que possuem essas slugs.

Por exemplo, se você tiver uma página cujo slug é "sample-page" e você definir como pai para ela, o CPT "meu-portal" WordPress chama:

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

mas não retorna nenhum resultado porque procura por uma página com slug 'sample-page' cujo pai é outra page com slug 'my-portal' . Essa página não existe, então você recebe o erro 404.

No entanto, get_page_by_path() aceita como terceiro argumento uma matriz de tipos de postagem: se você a definir como array('page', 'portal') , a função poderá encontrar a página corretamente.

Assim, você pode resolver o problema configurando manualmente o id da página (recuperado conforme explicado acima) nas consultas de WP.

O gancho 'parse_request' é perfeito para o escopo:

  • é executado depois que o URL foi analisado
  • ele passa para enganchar retornos de chamada a instância do objeto $wp que você pode usar para definir consultas de pesquisa

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, em combinação com o filtro no OP, é tudo o que você precisa.

Observe que o código funciona mesmo com portais hierárquicos aninhados.

    
por gmazzap 29.01.2015 / 08:13
0

A resposta do @gmazzap foi um ponto na direção certa. No entanto, por qualquer motivo, var_dump($wp->query_vars) estava mostrando apenas uma matriz com uma chave, attachment , o que não ajudou em nada.

No entanto, fez mostrar como eu poderia conseguir isso usando um pouco mais de truques.

O script abaixo recebe uma página apenas se a hierarquia estiver correta; ou seja, cada pai do slug corresponde a um post com o slug apropriado ( 0 para o primeiro slug, é claro).

Além disso, ele pula os caminhos com 0 ou 1 slugs simplesmente porque eles geralmente significam páginas especiais que o WordPress deve manipular (também, isso não importa realmente em termos de hierarquia de páginas ...)

E não, a consulta não pode ser muito otimizada. Isso se deve ao fato do MySQL não suportar seleções / junções recursivas como você gostaria em um modelo de dados hierá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 ];
  }
});
    
por 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.
  }

Tente esta resposta por: enlace

    
por TTech IT Solutions 26.01.2015 / 10:29