基于ACF字段创建固定链接

时间:2018-05-28 作者:Zeth

这既是一个关于“如何做到这一点”的问题,也是一个关于“我应该做到这一点”的问题。

我有一个ACF heavy站点,我想在其中基于一个ACF字段(我们称之为foo). 如果foo-字段具有值123, 那么我希望该页面的永久链接是http://example.org/s123 (thes 是为了避免与permalink中的post id发生冲突)。如果该URL被占用,那么它应该调用它http://example.org/s123-1 等等

ACF字段是在自定义的帖子类型上设置的。该网站包含一些重要信息,因此我宁愿不使用此功能,也不愿使用插件。所以它必须是functions.php-文件

有可能做到这一点吗?弄乱WordPress的永久链接结构(除了永久链接设置页面中允许的内容)是不是不明智?

Addition

我可以看出,如果你让CPT有“根”-永久链接,那么breaks the permalinks for posts and pages. :-/

... 我不知道让CPT有一个好的/简单的永久链接有这么难。

2 个回复
最合适的回答,由SO网友:Krzysiek Dróżdż 整理而成

由CF生成的URL好吧,您可以通过多种方式实现这一点。。。其中之一就是使用parse_request 过滤和修改它的行为,但它很容易搞糟一些事情。

另一种方法是使用save_post 操作并修改帖子post_name, 所以WordPress会像正常一样工作,但是post_name 将根据自定义字段而不是标题生成。这就是我想要的解决方案。为什么?因为你可以使用WP函数来确保链接是唯一的。。。

下面是代码:

function change_post_name_on_save($post_ID, $post, $update ) {
    global $wpdb;

    $post = get_post( $post_ID );
    $cf_post_name = wp_unique_post_slug( sanitize_title( \'s\' . get_post_field(\'foo\', $post_ID), $post_ID ), $post_ID, $post->post_status, $post->post_type, $post->post_parent );

    if ( ! in_array( $post->post_status, array( \'publish\', \'trash\' ) ) ) {
        // no changes for post that is already published or trashed
        $wpdb->update( $wpdb->posts, array( \'post_name\' => $cf_post_name ), array( \'ID\' => $post_ID ) );
        clean_post_cache( $post_ID );
    } elseif ( \'publish\' == $post->post_status ) {
        if ( $post->ID == $post->post_name ) {
            // it was published just now
            $wpdb->update( $wpdb->posts, array( \'post_name\' => $cf_post_name ), array( \'ID\' => $post_ID ) );
            clean_post_cache( $post_ID );
        }
    }
}
add_action( \'save_post\', \'change_post_name_on_save\', 20, 3 );
它不是最漂亮的,因为ACF字段保存在帖子之后,所以您必须覆盖post_name 帖子保存后。但它应该工作得很好。

根目录中的CPT,还有问题的第二部分:如何在没有CPT slug的情况下创建CPTs URL。。。

WordPress使用重写规则来解析请求。这意味着,如果请求与其中一条规则匹配,则将使用该规则对其进行解析。

页面规则是为捕获大多数与任何早期规则都不匹配的请求而制定的最后一条规则之一。所以,如果您添加没有任何slug的CPT,那么页面规则将不会启动。。。

解决这个问题的一种方法是用slug注册CPT,然后更改它们的链接和WPs行为。代码如下:

function register_mycpt() {
    $arguments = array(
        \'label\' => \'MyCPT\',
        \'public\' => true,
        \'hierarchical\' => false,
        ...
        \'has_archive\' => false,
        \'rewrite\' => true
    );
    register_post_type(\'mycpt\', $arguments);
}
add_action( \'init\', \'register_mycpt\' );
现在,这些帖子的URL如下所示:

http://example.com/mycpt/{post_name}/
但我们可以使用post_type_link 过滤器:

function change_mycpt_post_type_link( $url, $post, $leavename ) {
    if ( \'mycpt\' == $post->post_type ) {
        $url = site_url(\'/\') . $post->post_name . \'/\';
    }

    return $url;
}
add_filter( \'post_type_link\', \'change_mycpt_post_type_link\', 10, 3 );
现在URL将是正确的,但是。。。他们不会工作的。它们将使用页面重写规则进行解析,并将导致404错误(因为没有包含此类URL的页面)。但我们也可以解决这个问题:

function try_mycpt_before_page_in_parse_request( $wp ) {
    global $wpdb;

    if ( is_admin() ) return;

    if ( array_key_exists( \'name\', $wp->query_vars ) ) {
        $post_name = $wp->query_vars[\'name\'];

        $id = $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s ",
            \'mycpt\', $post_name
        ) );

        if ( $id ) {
            $wp->query_vars[\'mycpt\'] = $post_name;
            $wp->query_vars[\'post_type\'] = \'mycpt\';
        }

    }
}
add_action( \'parse_request\', \'try_mycpt_before_page_in_parse_request\' );

SO网友:DevLime

这可能过于简化了我正在阅读的内容,但不是使用ACF字段来控制永久链接,要修改URL中的永久链接,最简单的方法是在特定帖子/页面的编辑页面中编辑永久链接,而不是通过编程方式。

如果这更复杂,您可能需要查看WP_Rewrite API 并用它创建自定义逻辑。

此外,您可以rewrite the permalink structure 在CPT声明中

结束
基于ACF字段创建固定链接 - 小码农CODE - 行之有效找到问题解决它

基于ACF字段创建固定链接

时间:2018-05-28 作者:Zeth

这既是一个关于“如何做到这一点”的问题,也是一个关于“我应该做到这一点”的问题。

我有一个ACF heavy站点,我想在其中基于一个ACF字段(我们称之为foo). 如果foo-字段具有值123, 那么我希望该页面的永久链接是http://example.org/s123 (thes 是为了避免与permalink中的post id发生冲突)。如果该URL被占用,那么它应该调用它http://example.org/s123-1 等等

ACF字段是在自定义的帖子类型上设置的。该网站包含一些重要信息,因此我宁愿不使用此功能,也不愿使用插件。所以它必须是functions.php-文件

有可能做到这一点吗?弄乱WordPress的永久链接结构(除了永久链接设置页面中允许的内容)是不是不明智?

Addition

我可以看出,如果你让CPT有“根”-永久链接,那么breaks the permalinks for posts and pages. :-/

... 我不知道让CPT有一个好的/简单的永久链接有这么难。

2 个回复
最合适的回答,由SO网友:Krzysiek Dróżdż 整理而成

由CF生成的URL好吧,您可以通过多种方式实现这一点。。。其中之一就是使用parse_request 过滤和修改它的行为,但它很容易搞糟一些事情。

另一种方法是使用save_post 操作并修改帖子post_name, 所以WordPress会像正常一样工作,但是post_name 将根据自定义字段而不是标题生成。这就是我想要的解决方案。为什么?因为你可以使用WP函数来确保链接是唯一的。。。

下面是代码:

function change_post_name_on_save($post_ID, $post, $update ) {
    global $wpdb;

    $post = get_post( $post_ID );
    $cf_post_name = wp_unique_post_slug( sanitize_title( \'s\' . get_post_field(\'foo\', $post_ID), $post_ID ), $post_ID, $post->post_status, $post->post_type, $post->post_parent );

    if ( ! in_array( $post->post_status, array( \'publish\', \'trash\' ) ) ) {
        // no changes for post that is already published or trashed
        $wpdb->update( $wpdb->posts, array( \'post_name\' => $cf_post_name ), array( \'ID\' => $post_ID ) );
        clean_post_cache( $post_ID );
    } elseif ( \'publish\' == $post->post_status ) {
        if ( $post->ID == $post->post_name ) {
            // it was published just now
            $wpdb->update( $wpdb->posts, array( \'post_name\' => $cf_post_name ), array( \'ID\' => $post_ID ) );
            clean_post_cache( $post_ID );
        }
    }
}
add_action( \'save_post\', \'change_post_name_on_save\', 20, 3 );
它不是最漂亮的,因为ACF字段保存在帖子之后,所以您必须覆盖post_name 帖子保存后。但它应该工作得很好。

根目录中的CPT,还有问题的第二部分:如何在没有CPT slug的情况下创建CPTs URL。。。

WordPress使用重写规则来解析请求。这意味着,如果请求与其中一条规则匹配,则将使用该规则对其进行解析。

页面规则是为捕获大多数与任何早期规则都不匹配的请求而制定的最后一条规则之一。所以,如果您添加没有任何slug的CPT,那么页面规则将不会启动。。。

解决这个问题的一种方法是用slug注册CPT,然后更改它们的链接和WPs行为。代码如下:

function register_mycpt() {
    $arguments = array(
        \'label\' => \'MyCPT\',
        \'public\' => true,
        \'hierarchical\' => false,
        ...
        \'has_archive\' => false,
        \'rewrite\' => true
    );
    register_post_type(\'mycpt\', $arguments);
}
add_action( \'init\', \'register_mycpt\' );
现在,这些帖子的URL如下所示:

http://example.com/mycpt/{post_name}/
但我们可以使用post_type_link 过滤器:

function change_mycpt_post_type_link( $url, $post, $leavename ) {
    if ( \'mycpt\' == $post->post_type ) {
        $url = site_url(\'/\') . $post->post_name . \'/\';
    }

    return $url;
}
add_filter( \'post_type_link\', \'change_mycpt_post_type_link\', 10, 3 );
现在URL将是正确的,但是。。。他们不会工作的。它们将使用页面重写规则进行解析,并将导致404错误(因为没有包含此类URL的页面)。但我们也可以解决这个问题:

function try_mycpt_before_page_in_parse_request( $wp ) {
    global $wpdb;

    if ( is_admin() ) return;

    if ( array_key_exists( \'name\', $wp->query_vars ) ) {
        $post_name = $wp->query_vars[\'name\'];

        $id = $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s ",
            \'mycpt\', $post_name
        ) );

        if ( $id ) {
            $wp->query_vars[\'mycpt\'] = $post_name;
            $wp->query_vars[\'post_type\'] = \'mycpt\';
        }

    }
}
add_action( \'parse_request\', \'try_mycpt_before_page_in_parse_request\' );

SO网友:DevLime

这可能过于简化了我正在阅读的内容,但不是使用ACF字段来控制永久链接,要修改URL中的永久链接,最简单的方法是在特定帖子/页面的编辑页面中编辑永久链接,而不是通过编程方式。

如果这更复杂,您可能需要查看WP_Rewrite API 并用它创建自定义逻辑。

此外,您可以rewrite the permalink structure 在CPT声明中

相关推荐

Permalinks - Archives

WordPress文档说:WordPress offers you the ability to create a custom URL structure for your permalinks and archives. https://codex.wordpress.org/Settings_Permalinks_Screen 我看到此屏幕将如何为特定帖子/页面创建永久链接,但我没有看到此设置屏幕上关于如何为存档帖子/页面创建链接的任何其他详细信息。有人能澄清一下吗?