作为页面父级的自定义帖子类型

时间:2015-01-26 作者:Qix - MONICA WAS MISTREATED

因此,关于如何将页面作为自定义帖子类型的父级来获取,有一百万个代码片段。

然而,相反的情况似乎值得怀疑。有人会想,既然WordPress中的所有内容在技术上都是一篇“帖子”,这将是微不足道的。然而,事实并非如此。

到目前为止,我已经:

add_filter( \'page_attributes_dropdown_pages_args\',
  function( $dropdown_args, $post = null ) {
    $dropdown_args[\'post_type\'] = \'portal\';
    return $dropdown_args;
  } );
果然,页面现在允许我选择portal-键入posts作为父级。这些URL似乎在wordpress中注册正确,尽管它们都是404。

我怎样才能让wordpress理解这个层次结构并加载以帖子为父的页面?

3 个回复
最合适的回答,由SO网友:gmazzap 整理而成

WordPress使用一组重写规则将url转换为数据库查询。

处理页面URL的正则表达式非常通用,IIRC类似(.+.?)/?, 事实上,一切都还没有被其他规则所匹配。

因此,无法编写适用于您的情况的重写规则:因为您无法通过regex区分url中的example.com/my-portal/sample-page “我的门户”部分是CPT和sample-page 是一页。

如果嵌套级别更高,事情就会变得更复杂:my-portal/my-portal-child/sample-page.

为了处理这种URL,WordPress使用get_page_by_path() 功能:将页面url分解为/, 获取页段塞,然后查询数据库中的所有pages 有鼻涕虫的。

E、 g如果您有一个slug为“sample page”的页面,并且您将其设置为父页面,则CPT“my portal”会调用:

get_page_by_path(\'my-portal/sample-page\')
但是它doesn\'t 返回任何结果,因为它查找具有slug“sample page”且其父级为另一个的页面page 使用slug“我的门户”。该页面不存在,因此出现404错误。

然而get_page_by_path() 接受post类型数组作为第三个参数:如果将其设置为array(\'page\', \'portal\') 然后,该函数将能够正确找到页面。

因此,您可以通过手动将页面id(如上所述检索)设置到WP查询变量中来解决此问题。

这个\'parse_request\' 挂钩适用于以下范围:

它在解析url后运行,并传递给挂接回调实例$wp 对象可用于设置查询变量代码:

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
    }
  }
});
这段代码,再加上OP中的过滤器,就是您所需要的全部。

请注意,代码甚至可以与嵌套的分层门户一起使用。

SO网友:Qix - MONICA WAS MISTREATED

所以@gmazzapanswer 这是一个正确的方向。然而,无论出于何种原因,var_dump($wp->query_vars) 只显示了一个带有一个键的数组,attachment, 这根本没用。

然而,它确实显示了我如何使用更多的技巧来实现这一点。

只有当层次结构正确时,下面的脚本才能获取页面;也就是说,每个slug的父级将一个post与相应的slug匹配(0 当然是第一个弹头)。

此外,它跳过带有0或1个slug的路径,因为这些通常意味着WordPress应该处理的特殊页面(而且,就页面层次结构而言,这并不重要……)

不,查询不能进行太多优化。这是因为MySQL不支持递归选择/连接,就像您在层次数据模型中所希望的那样。

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 ];
  }
});

SO网友:TTech IT Solutions

  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.
  }
通过以下方式尝试此答案:http://janina.tumblr.com/post/3588081423/post-parent-different-type

结束

相关推荐

WP_DROPDOWN_PAGES不适用于POST_TYPE参数

我正在尝试显示带有自定义“post\\u type”帖子的下拉菜单。如果我插入这段代码,它会显示包含所有“页面”的下拉菜单。$arg=array( \'show_option_none\' => __( \'None\' ), \'orderby\' => \'title\', \'hide_empty\' => false, \'suppress_filter