第一步是注册post类型。slug在这里并不重要,我们不会使用注册post类型时生成的任何规则。
在此相同范围内init
函数中,我们添加了一个重写标记,并使用permalink模式进行了permastruct。这将使我们很容易在稍后添加的过滤器中构造永久链接。
最后一位是将传入请求映射到正确查询变量的重写规则。要按帖子ID查询自定义帖子类型,需要设置post_type
和p
查询变量。
function wpd_test_cpt() {
$args = array(
\'label\' => \'My CPT\',
\'public\' => true,
\'rewrite\' => [
\'slug\' => \'my_cpt\',
\'with_front\' => false,
],
);
register_post_type( \'my_cpt\', $args );
add_rewrite_tag( \'%foo_or_bar%\', \'([^/]+)\' );
add_permastruct( \'my_cpt\', \'fixed-word/%foo_or_bar%/%post_id%/\' );
add_rewrite_rule(
\'fixed-word/([^/]+)/([0-9]+)/?$\',
\'index.php?post_type=my_cpt&foo_or_bar=$matches[1]&p=$matches[2]\',
\'top\'
);
}
add_action( \'init\', \'wpd_test_cpt\' );
下一步是
post_type_link
为占位符交换值的过滤器:
function wpd_test_post_type_link( $permalink, $post ) {
if ( \'my_cpt\' === $post->post_type ) {
if( $choice = get_field( \'foo_or_bar\', $post->ID ) ) {
$permalink = str_replace( [\'%foo_or_bar%\', \'%post_id%\'], [$choice, $post->ID], $permalink );
}
}
return $permalink;
}
add_filter( \'post_type_link\', \'wpd_test_post_type_link\', 10, 2 );
现在这一切都应该按原样进行,但你可能会注意到一个小怪癖——你可以改变
foo
或
bar
无论您想要什么,查询仍然成功。你不能通过元数据来优化单一视图,WordPress认为帖子是存在的,而不仅仅是ID或slug。
要改变这一点,我们可以添加一些代码来检查foo_or_bar
,并确保它与请求的帖子ID匹配。如果不匹配,我们将重定向到正确的URL:
function wpd_test_pre_get( $query ) {
if ( isset( $query->query[\'foo_or_bar\'] ) && isset( $query->query[\'p\'] ) ) {
if( $choice = get_field( \'foo_or_bar\', $query->query[\'p\'] ) ){
if( $choice != $query->query[\'foo_or_bar\'] ){
wp_redirect( get_permalink( $query->query[\'p\'] ) );
}
}
}
}
add_action( \'pre_get_posts\', \'wpd_test_pre_get\' );