【问题标题】:wordpress: how to add hierarchy to postswordpress:如何为帖子添加层次结构
【发布时间】:2012-05-31 19:55:56
【问题描述】:

我正在 wordpress 平台上创建一个网站,我希望能够在其中发布我自己的书籍文本。所以我想要的是有某种层次结构,我会添加一个帖子,然后向它添加子项(章节)。我发现了这个:

register_post_type( 'post', array(
        'labels' => array(
            'name_admin_bar' => _x( 'Post', 'add new on admin bar' ),
        ),
        'public'  => true,
        '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
        '_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
        'capability_type' => 'post',
        'map_meta_cap' => true,
        'hierarchical' => false,
        'rewrite' => false,
        'query_var' => false,
        'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats' ),
    ) );

并尝试制作'hierarchical"=>true,但没有效果。有人可以帮忙吗?

【问题讨论】:

    标签: wordpress post hierarchy


    【解决方案1】:
    WordPress 中的

    帖子 应该是典型的按时间顺序排列的博客帖子。 页面是为静态内容制作的,它们可以开箱即用地组织成层次结构。

    对于任何页面,您都可以选择父页面。这样,您可以创建具有多个子级的嵌套层次结构。听起来像你需要的。

    查看Wordpress Documentation了解详情。

    如果你有一个深而复杂的树结构,一个插件可能会帮助你管理它,比如Wordpress Page Tree。它提供了比默认的 Wordpress 页面列表更好的界面。

    【讨论】:

    • 问题是我也希望用户能够发帖。而且由于安全原因,我无法为他们提供添加页面的能力:(我还为此找到了一个插件,但它不允许添加类别:“通用父子自定义帖子类型”。也许有任何方法可以添加类别到插件。你知道我该怎么做吗?
    • 那是一个完全不同的问题。为什么要让用户添加 Posts(或事件自定义帖子类型)而不是 Pages?也许您应该打开另一个问题来描述您要实现的用户交互类型。
    【解决方案2】:

    最好的解决方案是创建自定义分类法 [1]:http://codex.wordpress.org/Function_Reference/register_taxonomy 并创建主要的 slug - 书籍或其他东西。

    【讨论】:

      【解决方案3】:

      使用CPT UI 之类的插件,您可以创建自定义帖子类型并将其设置为具有分层树。

      然后只需检查帖子类型page-attribute 是否已设置为此自定义帖子类型和voile,您的帖子现在具有分层状态。

      https://wordpress.org/plugins/custom-post-type-ui/

      【讨论】:

        【解决方案4】:

        这是我的解决方法。这正是您想要的,能够为内置帖子类型帖子设置帖子父级。您可以通过向registred_post_type 操作挂钩添加操作来实现此目的。只需将其添加到主题的 functions.php 中即可。

        add_action('registered_post_type', 'igy2411_make_posts_hierarchical', 10, 2 );
        
        // Runs after each post type is registered
        function igy2411_make_posts_hierarchical($post_type, $pto){
        
            // Return, if not post type posts
            if ($post_type != 'post') return;
        
            // access $wp_post_types global variable
            global $wp_post_types;
        
            // Set post type "post" to be hierarchical
            $wp_post_types['post']->hierarchical = 1;
        
            // Add page attributes to post backend
            // This adds the box to set up parent and menu order on edit posts.
            add_post_type_support( 'post', 'page-attributes' );
        
        }
        

        使帖子分层可能会有所帮助的原因有很多。我的用例是客户希望将他们的(已经存在的)帖子组织成问题,其中子帖子是一个问题的文章(父帖子)。

        这很容易通过将查询限制为仅显示没有父母的帖子来实现。

         'post_parent' => 0,
        

        在您的查询 $args 中。

        【讨论】:

        • 不错。不过,你有一个额外的右括号。应该是:add_action('registered_post_type', 'igy2411_make_posts_hierarchical', 10, 2);
        • 似乎不再起作用(WP 5.3)。 stackoverflow.com/a/49359200/1165132 中的解决方案对我有用。
        • 很好的解决方案,除了帖子不带父项
        • 在版本 5.7.2 上使用此代码时,“父帖子”字段不显示。我需要使用这个过滤器developer.wordpress.org/reference/hooks/… 并将'parent_item_colon' 属性设置为'Parent Post'。
        【解决方案5】:

        存在插件,为post创建层次结构:

        https://wordpress.org/plugins/add-hierarchy-parent-to-post/

        【讨论】:

        • 我尝试使用这个插件 - 因为我很着急。但是它有一堆错误和粗略的代码(很多被注释掉的垃圾),并强制下载父插件公司在所有插件中使用的一些通用配置文件。看起来像一堆过时的软件......它还破坏了在实施后向我展示的页面。我不推荐这个插件。
        【解决方案6】:

        WP 4.9.*

        上面的解决方法让友好的 URL 变得疯狂。

        我为任何现有帖子类型添加层次结构的解决方案:

        add_filter( 'register_post_type_args', 'add_hierarchy_support', 10, 2 );
        function add_hierarchy_support( $args, $post_type ){
        
            if ($post_type === 'post') { // <-- enter desired post type here
        
                $args['hierarchical'] = true;
                $args['supports'] = array_merge($args['supports'], array ('page-attributes') );
            }
        
            return $args;
        }
        

        在 /wp-admin/options-permalink.php 中重新保存 wp 设置

        【讨论】:

        • 什么样的友好网址?因为我注意到我无法获得 /parent-post-slug/child-post-slug/ 中的分层 URL,而只会获得 /child-post-slug/
        • 它可以工作,但是为什么它将菜单项名称从“发布”更改为“页面”?现在我在侧边栏上看到了两个“页面”菜单项。
        【解决方案7】:

        这不是更好的选择吗?

        register_post_type( 'MYPOSTTYPE',
            array(
                'labels' => array(
                    'name' => __( 'MYPOSTTYPE' ),
                    'singular_name' => __( 'MYPOSTTYPE' )
                ),
                'supports' => array('title', 'editor', 'page-attributes'),
                'public' => true,
                'has_archive' => true,
                'hierarchical' => true,
                'rewrite' => array('slug' => 'MYPOSTTYPE'),
            )
        );
        

        我已添加:

        '分层' => true,

        它有效。

        【讨论】:

        • 另外,为了让它工作,你必须已经发布了一些东西!并且您的“支持”=> 数组缺少“页面属性”。
        • 我讨厌使用自定义帖子类型的原因是它会强制使用整个层到 URL /my-post-type/,如果您将一堆孤岛放置,这实际上对 SEO 目的非常不利这里的内容 - 比如可能有主题的文章。为每个主题区域创建新的帖子类型很烦人。我想您可以在帖子上使用类别,但我不喜欢处理 wordpress 数据库中的类别 - 分类法涉及很多连接。
        【解决方案8】:

        我来这里是为了实现:

        1. 为 post_type 帖子添加页面属性以添加父帖子
        2. 能够将页面模板添加到 post_type 帖子
        3. 能够获得 post_type 帖子的分层永久链接结构

        我可以使用the accepted answer 完成 1 和 2,但不能完成 3。

        注意:要完全让 2 工作,您需要在页面模板的模板 cmets 中指定 post_type,如下所示:

        <?php
        /*
        Template Name: Your Post Template Name
        Template Post Type: post
        */
        

        对于 3,我发现一个插件破坏了我的 post_type 页面,而且它有很多非常糟糕、无人维护的代码。

        所以我写了一个解决方案来完成这一切,借用this answer

        (用 4.9.8 测试)

        <?php
        
        add_action('registered_post_type', 'make_posts_hierarchical', 10, 2 );
        
        // Runs after each post type is registered
        function make_posts_hierarchical($post_type, $pto){
        
            // Return, if not post type posts
            if ($post_type != 'post') return;
        
            // access $wp_post_types global variable
            global $wp_post_types;
        
            // Set post type "post" to be hierarchical
            $wp_post_types['post']->hierarchical = 1;
        
            // Add page attributes to post backend
            // This adds the box to set up parent and menu order on edit posts.
            add_post_type_support( 'post', 'page-attributes' );
        
        }
        
        /**
         * Get parent post slug
         * 
         * Helpful function to get the post name of a posts parent
         */
        function get_parent_post_slug($post) {
          if (!is_object($post) || !$post->post_parent) {
            return false;
          }
        
          return get_post($post->post_parent)->post_name;
        }
        
        /**
         * 
         * Edit View of Permalink
         * 
         * This affects editing permalinks, and $permalink is an array [template, replacement]
         * where replacement is the post_name and template has %postname% in it.
         * 
         **/
        add_filter('get_sample_permalink', function($permalink, $post_id, $title, $name, $post) {
          if ($post->post_type != 'post' || !$post->post_parent) {
            return $permalink;
          }
        
          // Deconstruct the permalink parts
          $template_permalink = current($permalink);
          $replacement_permalink = next($permalink);
        
          // Find string
          $postname_string = '/%postname%/';
        
          // Get parent post
          $parent_slug = get_parent_post_slug($post);
        
          $altered_template_with_parent_slug = '/' . $parent_slug . $postname_string;
          $new_template = str_replace($postname_string, $altered_template_with_parent_slug, $template_permalink);
        
          $new_permalink = [$new_template, $replacement_permalink];
        
          return $new_permalink;
        }, 99, 5);
        
        /**
         * Alter the link to the post
         * 
         * This affects get_permalink, the_permalink etc. 
         * This will be the target of the edit permalink link too.
         * 
         * Note: only fires on "post" post types.
         */
        add_filter('post_link', function($post_link, $post, $leavename){
        
          if ($post->post_type != 'post' || !$post->post_parent) {
            return $post_link;
          }
        
          $parent_slug = get_parent_post_slug($post);
          $new_post_link = str_replace($post->post_name, $parent_slug . '/' . $post->post_name, $post_link);
        
          return $new_post_link;
        }, 99, 3);
        
        /**
         * Before getting posts
         * 
         * Has to do with routing... adjusts the main query settings
         * 
         */
        add_action('pre_get_posts', function($query){
          global $wpdb, $wp_query;
        
          $original_query = $query;
          $uri = $_SERVER['REQUEST_URI'];
        
          // Do not do this post check all the time
          if ( $query->is_main_query() && !is_admin()) {
        
            // get the post_name
            $basename = basename($uri);
            // find out if we have a post that matches this post_name
            $test_query = sprintf("select * from $wpdb->posts where post_type = '%s' and post_name = '%s';", 'post', $basename);
            $result = $wpdb->get_results($test_query);
        
            // if no match, return default query, or if there's no parent post, this is not necessary
            if (!($post = current($result)) || !$post->post_parent) {
              return $original_query;
            }
        
            // get the parent slug
            $parent_slug = get_parent_post_slug($post);
            // concat the parent slug with the post_name to get most of the url
            $hierarchal_slug = $parent_slug . '/' . $post->post_name;
        
            // if the concat of parent-slug/post-name is not in the uri, this is not the right post.
            if (!stristr($uri, $hierarchal_slug)) {
              return $original_query;
            }
        
            // pretty high confidence that we need to override the query.
            $query->query_vars['post_type'] = ['post'];
            $query->is_home     = false; 
            $query->is_page     = true;  
            $query->is_single   = true; 
            $query->queried_object_id = $post->ID;  
            $query->set('page_id', $post->ID);
        
            return $query;
          }
        
        
        }, 1);
        

        您可以将其保存到文件custom-posts-hierarchy.php 并将其包含在主题的functions.php 文件中,或者您可以添加到顶部:

        /*
        Plugin Name: Custom Posts Hierarchy
        Plugin URI:
        Description: Add page attributes to posts and support hiearchichal
        Author: Angela Murrell
        Version:
        Author URI: 
        */
        

        并将其放入您的插件文件夹中。祝你好运!

        【讨论】:

        • 父 slug 对我不起作用,永久链接中只是空白,所以你最终得到 //post-slug - 可能是因为我的父帖子在草稿中。父 post 对象没有 post_name 值。很奇怪。
        • 已确认。已发布帖子,然后重新保存为草稿,帖子 slug 现在可以正常工作了。
        • 是的,获取帖子父 slug 的函数正在寻找一个 post_name,因此您需要将其存储在您的父帖子中:return get_post($post-&gt;post_parent)-&gt;post_name; 如果发布可以帮助您完成此操作,那就这样做吧!
        • @amurrell 这允许创建一个帖子/hello 和另一个帖子/parent1/hello(这个帖子有parent1 作为父),这在很多情况下都非常有用!但是,问题是,当访问/parent1/hello 时,浏览器会将 URL 更改为/hello,而您会收到错误的帖子。你知道如何修改它吗?我为此开始了赏金。
        • @Basj 1- 你希望这种行为用于 wordpress 默认帖子吗?还是用于自定义帖子类型? 2-你能给我一张你的永久链接设置的截图吗?我想看看您是如何设置永久链接的。如果你能详细说明你正在寻找的细节,我会努力的!
        猜你喜欢
        • 2017-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多