当前位置: 首页>>技术解读>>正文


获得层次结构自定义帖子类型永久链接就像页面一样工作

webfans 技术解读 , , , 去评论

问题描述

我已经在自定义帖子类型的固定链接上挖掘了每个问题,但大多数似乎都是自定义分类标准重写的问题,或者明显缺少 flush_rewrite_rules()。但在我的情况下,我只使用自定义帖子类型(无分类),设置为分层(所以我可以分配parent-child关系),适当的”support”为属性元框等等,我刷新了重写规则千种不同的方式。我试过不同的permalink结构。但子网址总是会导致404!

我最初为”parent”和”child”元素(使用p2p)提供了独立的自定义帖子类型,并且我可能在使用”parental”分组的分类标准时没有问题 – 我知道这些分类在语义上更准确。但是对于客户端来说,当”posts”显示在管理中时,对于他们来说,最简单的方式就是像页面一样显示”posts”:一个简单的树,其子节点出现在父节点下方,以”–“为前缀,并按正确顺序排列。此外,可以使用通过drag-n-drop分配订单的各种方法。通过分类法(或p2p)进行分组会导致管理列表中的”posts”列表不再明显。

所以我所追求的是与”pages”核心完全相同的行为,但是使用我的自定义帖子类型。我已经按照预期注册了帖子类型,并且在管理中它完美地工作 – 我可以为每个新闻快讯”post”分配父母和menu_order,它们在编辑列表中正确显示:

Spring 2012
— First Article
— Second Article

他们的固定链接似乎是正确构建的。事实上,如果我更改了结构的任何内容,甚至在注册帖子类型时改变重写段落,他们会自动更新,所以我知道一些工作是正常的:

http://mysite.com/parent-page/child-page/                  /* works for pages! */
http://mysite.com/post-type/parent-post/child-post/        /* should work? */
http://mysite.com/newsletter/spring-2012/                  /* works! */
http://mysite.com/newsletter/spring-2012/first-article/    /* 404 */
http://mysite.com/newsletter/spring-2012/second-article/   /* 404 */

我也有创建了层次关系的标准核心”pages”,它们在管理员中看起来是一样的,但他们实际上也在front-end上工作(父母和子网址都可以正常工作)。

我的永久链接结构设置为:

http://mysite.com/%postname%/

我也试过这个(只是因为很多其他答案似乎表明它是需要的,尽管在我的情况下它没有意义):

http://mysite.com/%category%/%postname%/

我的注册CPT参数包括:

$args = array(
    'public'                => true,
    'publicly_queryable'    => true,
    'show_ui'               => true,
    'has_archive'           => 'newsletter',
    'hierarchical'          => true,
    'query_var'             => true,
    'supports'              => array( 'title', 'editor', 'thumbnail', 'page-attributes' ),
    'rewrite'               => array( 'slug' => 'newsletter', 'with_front' => false ),

我的自定义帖子类型的孩子和普通页面孩子之间唯一明显的区别是,我的CPT在永久链接结构的开始处有slu,,然后是父/子slu((其中页面以父/子slu开始,没有”prefix”)。为什么这会让事情变得糟糕,我不知道。大量的文章似乎表明,这正是CPT永久链接应该如何表现的行为 – 但我的,虽然很好地形成,却不起作用。

还有什么让我感到困惑的是,当我检查该页面的query_vars时 – 他们似乎包含WP到”find”我的子页面的正确值,但有些不起作用。

$wp_query object WP_Query {46}
public query_vars -> array (58)
'page' => integer 0
'newsletter' => string(25) "spring-2012/first-article"
'post_type' => string(10) "newsletter"
'name' => string(13) "first-article"
'error' => string(0) ""
'm' => integer 0
'p' => integer 0
'post_parent' => string(0) ""
'subpost' => string(0) ""
'subpost_id' => string(0) ""
'attachment' => string(0) ""
'attachment_id' => integer 0
'static' => string(0) ""
'pagename' => string(13) "first-article"
'page_id' => integer 0
[...]

我已经尝试过使用各种主题,包括二十二种,只是为了确保它不是我缺少的一些模板。

使用重写规则检查器,这是显示为URL:http://mysite.com/newsletter/spring-2012/first-article/

newsletter/(.+?)(/[0-9]+)?/?$   
       newsletter: spring-2012/first-article
           page: 
(.?.+?)(/[0-9]+)?/?$    
       pagename: newsletter/spring-2012/first-article
           page: 

它如何显示在另一个检查员页面上:

RULE:
newsletter/(.+?)(/[0-9]+)?/?$
REWRITE:
index.php?newsletter=$matches[1]&page=$matches[2]
SOURCE:
newsletter

这个重写输出会让我相信以下”non-pretty”永久链接可以工作:

http://mysite.com/?newsletter=spring-2012&page=first-article

它不是404,但它显示父CPT项目”newsletter”,而不是孩子。请求看起来像这样:

Array
(
    [page] => first-article
    [newsletter] => spring-2012
    [post_type] => newsletter
    [name] => spring-2012
)

最佳解决方案

这是我第一次参加Stack Exchange,但我会放弃这一点,看看我能否帮助你指出正确的方向。

默认情况下,分层CPT的行为与您所描述的完全相同。在这种情况下,独特的slug前缀”newsletter”是让重写引擎知道如何区分不同帖子类型的请求。

那些CPT注册参数看起来不错,但是当请求CPT时,pagename查询变量不应该有值,并且name查询变量应该与newsletter相同,因此看起来您的设置中存在冲突。

要帮助调试,安装并激活Rewrite Rules Inspector Plugin,请访问“工具 – >重写规则”屏幕。

  1. 在查看列表时,应该在任何页面重写规则之前列出CPT的所有规则。通过扫描”Source”列来验证情况。

  2. 如果检查出来,请在”Match URL”字段中输入”first-article” CPT的URL,然后单击”Filter”按钮查看匹配的规则。它应该符合通讯规则和页面规则,但通讯规则应该是第一个。

如果没有发现任何问题,请搜索wp_posts中的post_name列以查找”first-article” slu other的其他帖子,以查看是否可能发生碰撞。只需确保搜索”newsletter”。

添加以下片段以在请求的早期检查您的查询变量,以检查并通过重写规则匹配(请访问前端的子CPT)设置哪些变量。如果pagename var没有出现在这里,那么它将在稍后的请求中被设置:

add_filter( 'request', 'se77513_display_query_vars', 1 );

function se77513_display_query_vars( $query_vars ) {
    echo '<pre>' . print_r( $query_vars, true ) . '</pre>';

    return $query_vars;
}

任何修改查询变量的插件/函数都可能导致冲突,所以如果仍然有问题,请将其禁用。同样在每一步之后刷新重写规则,特别是如果请求在上面的第二步中匹配了错误的规则(保持”Permalinks”屏幕在单独的选项卡中打开并刷新它)。

次佳解决方案

parent/Child固定链接只要您设置就可以开箱即用

'hierarchical'=> true,
'supports' => array('page-attributes' ....

更新:

我只是再次测试它,并按预期工作,测试案例如下:

add_action('init','test_post_type_wpa77513');
function test_post_type_wpa77513(){
    $args = array(
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true, 
        'show_in_menu' => true, 
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'has_archive' => true, 
        'hierarchical' => true,
        'supports' => array( 'title', 'editor', 'thumbnail', 'page-attributes' )
    ); 

    register_post_type( 'newsletter', $args );
}

和永久设置/%postname%/我得到通讯/父母/孩子工作得很好。

第三种解决方案

除了询问»Have you tried turning it off and on again?«之外,我还必须问:“你有任何插件活跃,你的主题是否对固定链接做任何事情(例如:注册分类法,发布类型,添加重写规则等)?

如果是这样:在禁用所有插件并切换到TwentyEleven之后,这是否仍然发生?

custom-post-types,permalinks,404-error,wordpress

要进一步调试,请转到GitHub并抓取Toschos “Rewrite” Plugin。然后切换到官方插件回购on wp.org and grap the MonkeyManRewriteAnalyzer Plugin。我甚至写了一个小小的扩展,将两者粘合在一起。这会给你很多有关你的设置的细节。

第四种方案

因此,在确认可以通过完全干净的安装和单个CPT声明来获得预期的分层页面行为后,我知道故障位于我自己的插件中的某处,我用它来处理CPT创建(非常复杂,处理自定义元框,分类法等)。问题是,尽管所有的建议检查重写或查询问题,我看不出有什么明显的错误。我检查了每个过滤器和钩子,在每个点查看查询,并且没有看到会导致404的任何内容。

所以我只剩下9个大类中的每一个都需要手动禁用/启用任务,然后至少找到其中的2个导致404,逐个遍历每个函数并禁用/启用它们,然后跟踪行在这些功能中排队 – 一个暴力试图确切地看到什么导致404,即使我不知道为什么。

那时我发现使用$query->get_queried_object()会有一个结果。这似乎使用这个包装函数实际上修改$查询本身,我认为我在我的函数结束时没有改变。涉及修改查询的两个类的三个过滤器:parse_queryposts_orderbyposts_join – 并且所有回调函数都在传递的$query arg上调用$query->get_queried_object(),然后运行一些条件测试并有时修改查询变量(如特殊排序顺序例)。奇怪的是,尽管我使用了这个函数,但这些函数实际上在他们设计的目标上工作得很好。我从来没有注意到之前返回的$查询有什么问题!

不知何故,经过数十个现场制作网站的开发和使用已有一年多的时间,我从未经历过这个错误带来的任何不利影响。只有当我冒险进入分层CPT时,这一点小小的突破才会突破。这是我如此努力的一部分 – 尽我所知,我的查询过滤器值得信赖!

我承认,我仍然不清楚为什么调用这个函数打破了CPT子页面的这一小部分 – 但从未表现出任何其他问题!但很明显,在过滤器回调中使用它会以某种方式破坏返回的$query。通过删除这个调用,我的404错误消失了。

感谢所有的提示 – 希望我能分裂奖金,因为我从每个答案中获得了洞察力,即使最终解决方案有些不相关。这是一个教育课,不会盲目地信任你的代码,即使它长期以来一直在为你工作,或者它没有产生任何明显的错误。

有时候,当kaiser的图表如此整齐地体现时,你只需开始投掷开关,直到灯光再次亮起。就我而言,在我看到问题之前,我必须一直采用相同的故障排除策略,直到函数中的各个行。

参考资料

本文由朵颐IT整理自网络, 文章地址: https://duoyit.com/article/1993.html,转载请务必附带本地址声明。