Tim*_*rov 5 wordpress post hierarchy
我正在 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' ),
) );
Run Code Online (Sandbox Code Playgroud)
并试图制作'hierarchical"=>true
,但没有效果。任何人都可以帮忙吗?
小智 8
这是我的解决方法。这正是您想要的,能够为内置帖子类型帖子设置帖子父级。您可以通过向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' );
}
Run Code Online (Sandbox Code Playgroud)
使帖子分层可能有帮助的原因可能有很多。我的用例是客户想要将他们(已经存在的)帖子组织成问题,其中子帖子是一个问题(父帖子)的文章。
这可以通过将查询限制为仅显示没有父级的帖子来轻松实现,使用。
'post_parent' => 0,
Run Code Online (Sandbox Code Playgroud)
在您的查询 $args.
小智 7
可湿性粉剂 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;
}
Run Code Online (Sandbox Code Playgroud)
在 /wp-admin/options-permalink.php 重新保存 wp 设置
由于评论引发了新的用例和问题,我重写了这段代码,并在我自己的网站上使用它[在 5.8.2 中测试]。我已经提供了一个要点。您可以将其包含在您的functions.php中,或者将其放入插件中。
https://gist.github.com/amurrell/00d29a86fc1a773274bf049ef545b29f
此新更新利用 SQL(快速!)来解析 slug 和帖子 id 以确定永久链接和路由。它会生成完全匹配的帖子 id,即使您post_name
对不同的帖子后代使用相同的帖子 id 。它真的又快又可靠!
本质上,最有趣的功能是get_post_from_uri($uri)
让我们看看查询是如何工作的。这可能不是完美的 1-1 代码,因为我将其设为动态的,但概念是存在的:
我有以下帖子:
在 SQL 中查看:
mysql> select id, post_name, post_parent from wp_posts where post_type = 'post' and id in (1811, 1808, 1345, 1395, 547, 518);
+------+-------------------------+-------------+
| id | post_name | post_parent |
+------+-------------------------+-------------+
| 518 | procurement | 0 |
| 547 | climate | 0 |
| 1345 | city-sales-cycle | 518 |
| 1395 | alliance-for-innovation | 0 |
| 1808 | climate | 1395 |
| 1811 | climate | 1345 |
+------+-------------------------+-------------+
Run Code Online (Sandbox Code Playgroud)
alliance-for-innovation/climate
完整的查询...
mysql> select * from
-> (select TRIM(BOTH '/' FROM concat(
-> IFNULL(p3_slug,''),
-> '/',
-> IFNULL(p2_slug,''),
-> '/',
-> p1_slug
-> )
-> ) as slug,
-> id
-> from (
-> select d2.*, p3.post_name as p3_slug, p3.post_parent as p3_parent from (
-> select d1.*, p2.post_name as p2_slug, p2.post_parent as p2_parent from (
-> select id, post_name as p1_slug, post_parent as p1_parent from wp_posts where post_type = 'post' and post_name = 'climate'
-> ) as d1
-> left join wp_posts p2 on p2.id = d1.p1_parent
-> ) as d2
-> left join wp_posts p3 on p3.id = d2.p2_parent) as d3
->
-> ) as all_slugs
-> where slug = 'alliance-for-innovation/climate';
+---------------------------------+------+
| slug | id |
+---------------------------------+------+
| alliance-for-innovation/climate | 1808 |
+---------------------------------+------+
1 row in set (0.01 sec)
Run Code Online (Sandbox Code Playgroud)
我现在拥有帖子ID
和或永久链接slug
,我应该使用!
值得注意的是,我进入了 p3 级别,这是比 URL 所需的额外级别(分为两部分)。这是为了防止类似的事情alliance-for-innovation/climate/something
匹配。
有一个内部查询会查找 URL 的最后一部分,即基本名称。在这种情况下,它会是climate
。
mysql> select id, post_name as p1_slug, post_parent as p1_parent from wp_posts where post_type = 'post' and post_name = 'climate';
+------+---------+-----------+
| id | p1_slug | p1_parent |
+------+---------+-----------+
| 547 | climate | 0 |
| 1808 | climate | 1395 |
| 1811 | climate | 1345 |
+------+---------+-----------+
Run Code Online (Sandbox Code Playgroud)
/
以编程方式,我们不断在与 url 中的数量直接相关的查询周围添加抽象,以便我们可以找到有关 post_parent 的 slug 的更多信息。
mysql> select d1.*, p2.post_name as p2_slug, p2.post_parent as p2_parent from (
-> select id, post_name as p1_slug, post_parent as p1_parent from wp_posts where post_type = 'post' and post_name = 'climate'
-> ) as d1
-> left join wp_posts p2 on p2.id = d1.p1_parent;
+------+---------+-----------+-------------------------+-----------+
| id | p1_slug | p1_parent | p2_slug | p2_parent |
+------+---------+-----------+-------------------------+-----------+
| 547 | climate | 0 | NULL | NULL |
| 1808 | climate | 1395 | alliance-for-innovation | 0 |
| 1811 | climate | 1345 | city-sales-cycle | 518 |
+------+---------+-----------+-------------------------+-----------+
Run Code Online (Sandbox Code Playgroud)
在我们抽象足够多次之后,我们可以选择 concat 作为 slug,例如: p1_slug + '/' + p2_slug
mysql> select TRIM(BOTH '/' FROM concat(
-> IFNULL(p3_slug,''),
-> '/',
-> IFNULL(p2_slug,''),
-> '/',
-> p1_slug
-> )
-> ) as slug,
-> id
-> from (
-> select d2.*, p3.post_name as p3_slug, p3.post_parent as p3_parent from (
-> select d1.*, p2.post_name as p2_slug, p2.post_parent as p2_parent from (
-> select id, post_name as p1_slug, post_parent as p1_parent from wp_posts where post_type = 'post' and post_name = 'climate'
-> ) as d1
-> left join wp_posts p2 on p2.id = d1.p1_parent
-> ) as d2
-> left join wp_posts p3 on p3.id = d2.p2_parent) as d3
->
-> ;
+--------------------------------------+------+
| slug | id |
+--------------------------------------+------+
| climate | 547 |
| alliance-for-innovation/climate | 1808 |
| procurement/city-sales-cycle/climate | 1811 |
+--------------------------------------+------+
Run Code Online (Sandbox Code Playgroud)
where
最后一步是为原始 url添加 a : alliance-for-innovation/climate
。这就是您在我们首先检查的完整查询示例中看到的内容!
# climate
+---------+-----+
| slug | id |
+---------+-----+
| climate | 547 |
+---------+-----+
Run Code Online (Sandbox Code Playgroud)
# procurement/city-sales-cycle/climate
+--------------------------------------+------+
| slug | id |
+--------------------------------------+------+
| procurement/city-sales-cycle/climate | 1811 |
+--------------------------------------+------+
Run Code Online (Sandbox Code Playgroud)
转义climate
我们在查询中使用的 URL 的 , 或基名,因为这在技术上是用户输入的(通过 url)
$wpdb->_real_escape($basename));
Run Code Online (Sandbox Code Playgroud)
我们使用 PHP 数组、循环等来构建一个将作为查询的字符串,这样我们就不必使用 PHP 来处理有关数据本身的逻辑。
这是显示动态抽象的片段 - 例如。要抓取多少个 p1_slug、p2_slug、p3_slug。
// We will do 1 more depth level than we need to confirm the slug would not lazy match
// This for loop builds inside out.
for ($c = 1; $c < $depth + 2; $c++) {
$d = $c;
$p = $c + 1;
$pre = "select d${d}.*, p${p}.post_name as p${p}_slug, p${p}.post_parent as p${p}_parent from (";
$suf = ") as d${d} left join $wpdb->posts p${p} on p${p}.id = d${d}.p${c}_parent";
$sql = $pre . $sql . $suf;
$concats[] = sprintf("IFNULL(p${p}_slug,'')");
}
Run Code Online (Sandbox Code Playgroud)
我来到这里是为了实现:
我能够使用已接受的答案来完成 1 和 2,但不能完成 3。
注意:要完全让 2 工作,您需要在页面模板的模板注释中指定 post_type,如下所示:
<?php
/*
Template Name: Your Post Template Name
Template Post Type: post
*/
Run Code Online (Sandbox Code Playgroud)
对于 3,我发现一个插件毁了我的 post_type 页面,其中有很多非常糟糕的、未维护的代码。
因此,我借鉴了这个答案,编写了一个解决方案来完成这一切:
(用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);
Run Code Online (Sandbox Code Playgroud)
您可以将其保存到文件中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:
*/
Run Code Online (Sandbox Code Playgroud)
并将其放入您的插件文件夹中。祝你好运!
归档时间: |
|
查看次数: |
19531 次 |
最近记录: |