使用事件日期(年和月)而不是发布日期的固定链接

时间:2014-09-11 作者:Nik Dow

网站http://www.bikefun.org 生活和工作,但permalinks并不完全正确。这是一个活动日历网站。事件存储为自定义post类型“bf\\U Events”,日期存储为整数postETA值-由strotime()生成的整数。

我用的是permalink结构/events/2014/09/cyclewise-confidence-training-intermediate-2/ 其中年份和月份是事件日期,而不是帖子的发布日期。这在某种程度上是可行的,但实际上,WP只使用事件标题,并且WP添加了末尾的数字“2”,以保持永久链接的唯一性。如果更改年份或月份,将加载相同的页面,而您应该得到404。

代码如下:

function event_rewrite_rules() {
    global $wp_rewrite;

    $wp_rewrite->add_rewrite_tag( \'%eventyear%\', \'([0-9]{4})\', \'bf_events_year=\');
    $wp_rewrite->add_rewrite_tag( \'%eventmonth%\', \'([0-9]{2})\', \'bf_events_month=\');
    // $wp_rewrite->add_permastruct(\'bf_events\', \'/events/%bf_events_year%/%bf_events_month%/%postname%\', false);
    add_rewrite_rule(  \'^events/([0-9]{4})/([0-9]{2})/([^/]+)?\', \'index.php??post_type=bf_events&pagename=$matches[2]\', \'top\' );
}
add_action(\'init\', \'event_rewrite_rules\');
我对add\\u permastruct调用发表了评论,因为它破坏了一切。

add_filter(\'post_type_link\', \'event_permalink\', 10, 4);

function event_permalink($permalink, $post, $leavename) {
    if ( get_post_type( $post ) === "bf_events" ) {
        $sd = get_post_meta( $post->ID, \'bf_events_startdate\', true);
        $year = date(\'Y\', $sd + get_option( \'gmt_offset\' ) * 3600);
        $month = date(\'m\', $sd + get_option( \'gmt_offset\' ) * 3600);

        $rewritecode = array(
            \'%eventyear%\',
            \'%eventmonth%\',
            $leavename? \'\' : \'%postname%\',
        );

        $rewritereplace = array(
            $year,
            $month,
            $post->post_name
        );

        $permalink = str_replace($rewritecode, $rewritereplace, $permalink);
    }
    return $permalink;
}
为了使WP能够在permalink中使用年和月,这些值将作为附加的Posteta值存储在meta save函数中:

update_post_meta($post->ID, "bf_events_startdate", $updatestartd );
update_post_meta($post->ID, "bf_events_year", date("Y", $updatestartd ) );
update_post_meta($post->ID, "bf_events_month", date("m", $updatestartd ) );
编辑:我一直在将我的代码与插件“事件日历”进行比较。此插件插入日期(与我的格式不同)作为永久链接最后一个组件的一部分,并与事件标题连字号:cultural-center-art-exhibition-2014-11-08 请注意,如果您使用相同的名称创建第二篇文章,则WP会在永久链接的标题部分附加-2。然而,他们的代码比我的好,因为如果你更改永久链接的日期部分,你会得到一个404,而我的代码会加载事件,只要标题正确,并且你有任何匹配的内容/([0-9]{4})/([0-9]{2})/ 在permalink的日期部分。我将尝试找出他们是如何获得404的,并可能了解更多信息。

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

简而言之:您需要修改单个事件帖子的查询以包含元数据,因此只会返回具有匹配名称、年份和月份的帖子。

我将向您展示我用于测试此功能的完整代码。我对您的代码做了一些更改,并简化了一些内容,所以请小心更新所有函数。

首先,permalinks中使用的重写标记。不需要修改globals来添加这些,这里有一个函数。

function wpd_event_rewrite_tags() {
    add_rewrite_tag( \'%bf_events_year%\', \'([0-9]{4})\' );
    add_rewrite_tag( \'%bf_events_month%\', \'([0-9]{2})\' );
}
add_action( \'init\', \'wpd_event_rewrite_tags\' );
接下来是注册post类型。在这里,我们可以设置永久链接结构,而无需手动添加规则。请注意事件slug中重写标记的使用。我已经将其简化为一个工作示例的基本内容。

function wpd_event_post_type() {
    $args = array(
        \'public\' => true,
        \'label\'  => \'Events\',
        \'rewrite\' => array( \'slug\' => \'events/%bf_events_year%/%bf_events_month%\' ),
        \'supports\' => array( \'title\', \'editor\', \'custom-fields\' )
    );
    register_post_type( \'bf_events\', $args );
}
add_action( \'init\', \'wpd_event_post_type\' );
您的post_type_link 功能基本保持不变,只是更新了重写标记:

function wpd_event_permalink($permalink, $post, $leavename) {
    if ( get_post_type( $post ) === "bf_events" ) {
        $sd = get_post_meta( $post->ID, \'bf_events_startdate\', true);
        $year = date(\'Y\', $sd + get_option( \'gmt_offset\' ) * 3600);
        $month = date(\'m\', $sd + get_option( \'gmt_offset\' ) * 3600);

        $rewritecode = array(
            \'%bf_events_year%\',
            \'%bf_events_month%\',
            $leavename ? \'\' : \'%postname%\',
        );

        $rewritereplace = array(
            $year,
            $month,
            $post->post_name
        );

        $permalink = str_replace($rewritecode, $rewritereplace, $permalink);
    }
    return $permalink;
}
add_filter( \'post_type_link\', \'wpd_event_permalink\', 10, 4 );
谜题的最后一块是魔法发生的地方。这里,我们将月份和年份查询变量添加到元查询中。添加它也会启动规范重定向,因此它会重定向到正确的年/月,而不是返回404。

function wpd_single_event_queries( $query ){
    if( $query->is_singular()
        && $query->is_main_query()
        && isset( $query->query_vars[\'bf_events\'] ) ){
            $meta_query = array(
                array(
                    \'key\'     => \'bf_events_year\',
                    \'value\'   => $query->query_vars[\'bf_events_year\'],
                    \'compare\' => \'=\',
                    \'type\'    => \'numeric\',
                ),
                array(
                    \'key\'     => \'bf_events_month\',
                    \'value\'   => $query->query_vars[\'bf_events_month\'],
                    \'compare\' => \'=\',
                    \'type\'    => \'numeric\',
                ),
            );
            $query->set( \'meta_query\', $meta_query );
    }
}
add_action( \'pre_get_posts\', \'wpd_single_event_queries\' );

结束