带有/%postname%/ permastruct的Wordpress 3.3自定义帖子类型?


9

以前有一个标题相似的帖子,但它没有浏览WordPress 3.3,这一点很重要,因为3.3有趣地做广告:“使用postname永久链接结构,而不会降低性能”

Wordpress 3.2和更早版本的问题是,它首先查看页面名称,然后是404。它没有首先检查任意帖子类型。另一方面,3.3 必须查看帖子类型,然后是页面,最后是404(因为它宣传了此功能)。这意味着,如果没有在某处进行硬编码,则没有的自定义帖子类型应该很简单post_type=post

我还找不到3.3特定的解决方案。

问题:如何为任何给定的自定义帖子类型“ xyz”定义永久链接结构“ /%postname%/”?

谢谢。


我没有看到任何问题-您实际上在问什么?
特拉维斯·诺斯卡特

为了清楚起见,您想定义一个新的自定义帖子类型,该类型使用/%postname%/?的永久链接结构。您是否打算让帖子也使用这种相同的永久结构,或者它们会有前缀?
prettyboymp 2012年

接下来,看看是否有人想出答案。我也尝试了上述方法,同时将重写段设置为'/',这也破坏了页面永久链接。叹息……

Answers:


2

除非您将重写规则欺骗到正确的位置,并使wp_rewrite认为在前端使用了冗长的规则,否则在WP 3.3中很难做到这一点。以下课程适用。

class Test_Post_Type {
    const POST_TYPE = 'test';

    public static function init() {
        global $wp_rewrite;

        $post_type_obj = register_post_type( self::POST_TYPE, array(
            'labels' => array(
                'name' => __( 'Tests' ),
                'singular_name' => __( 'Test' ),
                'add_new' => __( 'Add New' ),
                'add_new_item' => __( 'Add New Test' ),
                'edit_item' => __( 'Edit Test' ),
                'new_item' => __( 'New Test' ),
                'all_items' => __( 'All Tests' ),
                'view_item' => __( 'View Test' ),
                'search_items' => __( 'Search Tests' ),
                'not_found' => __( 'No Tests found' ),
                'not_found_in_trash' => __( 'No Tests found in Trash' ),
                'menu_name' => __( 'Tests' )
            ),
            'publicly_queryable' => true,
            'exclude_from_search' => true,
            'hierarchical' => false,
            'public' => true,
            'rewrite' => false,
            'has_archive' => true,
            'supports' => array( 'title', 'editor', 'thumbnail', 'test_source' ),
            'taxonomies' => array( 'category', 'post_tag' ),
        ) );

        $post_type_obj = get_post_type_object(self::POST_TYPE);

        //register the rewrite tag for permalink building
        $wp_rewrite->add_rewrite_tag( '%' . $post_type_obj->query_var . '%', '([^/]+)', $post_type_obj->query_var . '=' );

        //we have to add the permastruct here in order to build the permalink, otherwise we'll need to filter the post_type link
        add_permastruct(self::POST_TYPE, '%' . $post_type_obj->query_var . '%/', false );

        //add a filter to remove the permastructs generated above
        add_filter(self::POST_TYPE . '_rewrite_rules', array(__CLASS__, '_remove_default_rules')); 

        //now we add a filter to put the generated rewrite rules in the correct spot
        add_action('generate_rewrite_rules', array(__CLASS__, '_filter_rewrite_rules'));

        if(!is_admin()) {
            //we need verbose_page_rules to be on on the front end in order for pages to be process properly
            $wp_rewrite->use_verbose_page_rules = true;
        }
    }

    /**
     * Filter to remove the rules for this post type when they're automatically generated due to the permastruct registration
     * @param type $rules
     * @return type 
     */
    public static function _remove_default_rules($rules) {
        return array();
    }

    /**
     * Filters the rules at the end to add back the ones for this post type at the bottom
     * @param WP_Rewrite $wp_rewrite 
     */
    public static function _filter_rewrite_rules($wp_rewrite) {
        $post_type_obj = get_post_type_object(self::POST_TYPE);
        $my_rules = $wp_rewrite->generate_rewrite_rules('%' . $post_type_obj->query_var . '%', EP_NONE);
        $wp_rewrite->rules += $my_rules;
    }

}

add_action( 'init', array( 'Test_Post_Type', 'init' ) );

复制将此代码粘贴到主题中,刷新重写规则。添加了一个新帖子,查看了该帖子(URL是正确的),得到了404 ...关于WP 3.3.1。知道为什么这对我不起作用吗?(感谢代码btw!)
Rob Vermeer 2012年

EP_NONE-> EP_PERMALINK可以使评论页面生效,然后要使多个帖子类型与/%postname%/一起使用,还必须使用parse_query过滤器。请参阅上面的答案。
Ciantic

Rob,您添加了新帖子还是添加了新的“测试”帖子?最初的问题尚不清楚,即帖子是否也需要具有/%post_name%/的永久结构。如果是这样,为什么还要创建一个新的帖子类型?另外,如果多个帖子类型具有相同的永久结构,则可能会出现名称冲突的问题。
prettyboymp 2012年

1

圣车钥匙!

我认为这可行。它几乎可以工作,非常简单,只有一行:

global $wp_rewrite;
$args = array(
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'query_var' => true,
    'rewrite' => array('slug' => 'anything'),
    'capability_type' => 'post',
    'has_archive' => true,
    'hierarchical' => false,
    'menu_position' => null,
    'supports' => array('title','editor','thumbnail')
);
register_post_type('my_custom_post_type', $args);

$wp_rewrite->add_permastruct('my_custom_post_type', "%my_custom_post_type%");

PS:如果您在家中尝试此操作,则添加这一行后,转到“设置”->“永久链接”并保存更改,它会刷新永久链接。

我正在阅读WP register_post_type()源代码,发现一行:

$wp_rewrite->add_permastruct($post_type, "{$args->rewrite['slug']}/%$post_type%", $args->rewrite['with_front'], $args->permalink_epmask);

不用说,但我不会之以鼻,我认为它应该可以工作,并且确实可以。即使在编辑器标题下的固定链接编辑也能正常工作!

更新:这会破坏页面永久链接,回到绘图板...


我也尝试过这个,结果也差不多。如果可以的话会很酷。也许有人有主意吗?
Rob Vermeer 2012年

@RobVermeer注意到,没有这一行(只有默认的子弹),WordPress已经能够重定向到该URL。例如,“ some-post”重定向到“ anything / some-post”。在codepeak中,在代码中的某处有对CPT的支持,而不会拖延,它默认是重定向。脸掌
Ciantic

1

prettyboymp的答案与我昨天得到的答案几乎相同,但我对此不满意。prettyboymp的回答有一个缺陷,当同时在多种帖子类型上使用/%postname%/时,它不起作用。

这是我的答案,该答案也针对当前结构,并创建了一系列后备类型。但是,如果两个帖子类型都具有相同的标记并且都为/%postname%/,那么这也有一个缺陷,那么它会同时显示两者。

class MyCustomPostType {
    /**
     * Register post type
     **/
    public static function register_post_type() {
        global $wp_rewrite;

        $args = array(
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => false,
            'capability_type' => 'post',
            'has_archive' => true,
            'hierarchical' => false,
            'menu_position' => null,
            'supports' => array('title','editor','thumbnail')
        );

        register_post_type('my_custom_post_type', $args);

        // Enables the pages to work simultaneously
        $wp_rewrite->use_verbose_page_rules = true;
        add_filter("rewrite_rules_array", array(__CLASS__, 'rewrite_rules_array'));
        add_action("parse_query", array(__CLASS__, 'parse_query'));
        add_filter("post_type_link", array(__CLASS__, 'post_type_link'), 1, 4);
    }

    public static function post_type_link($link, $post, $leavename=false, $sample=false) {
        if ($sample && ($begin = strpos($link, "?my_custom_post_type=")) !== false) {
            return substr($link, 0, $begin-1) . "/%my_custom_post_type%/";
        }
        return str_replace("?my_custom_post_type=", "", $link) . "/";
    }

    public static function parse_query($query) {
        global $wp, $wp_rewrite;

        // Is this query for /%post_name%/? Is it main request query?
        if (isset($query->query['name'])
            && substr($wp->matched_rule, 0, 7) == "([^/]+)"
            && isset($query->query)
            && isset($wp->query_vars)
            && $query->query == $wp->query_vars)
        {
            //echo '<p><h1>hit!</h1></p>';
            if (!($post_types = get_query_var("post_type"))) {
                if ($wp_rewrite->permalink_structure == "/%postname%/")
                    $post_types = array("post");
                else
                    $post_types = array();
            }

            if (is_array($post_types))
                $post_types[] = "my_custom_post_type";

            set_query_var("post_type", $post_types);
            //set_query_var("posts_per_page", 1);
        }
    }

    public static function rewrite_rules_array($array) {
        global $wp_rewrite;
        // Same rules as in /%post_name%/
        return array_merge($array, $wp_rewrite->generate_rewrite_rules("/%postname%/", EP_PERMALINK));
    }
}


add_action('init', array("MyCustomPostType", "register_post_type"));

某些帖子类型是否有可能成为分层的。我没有尝试过自己,但似乎没有任何工作......它认为后是一个带有附件的父/子/ ...如果我做父/子/孙子/它得到404
罗布维米尔

1

我创建了一个解决方案,但找不到任何问题。如果您发现问题,请尝试告诉我

add_action('init', 'firmasite_resimlitarif_cpt', 0);
function firmasite_resimlitarif_cpt() 
{

// Yemek Tarifi

  $args = array(
    'public' => true,
    'show_in_menu' => true, 
    'permalink_epmask' => EP_NONE,
    'rewrite' => array('slug'=>'/','with_front'=>false),
    'has_archive' => false,
    'supports' => array('title','editor','thumbnail')
  ); 
  register_post_type('yemek',$args);

}


// http://wordpress.stackexchange.com/questions/37650/wordpress-3-3-custom-post-type-with-postname-permastruct
add_action("parse_query", 'firmasite_resimlitarif_parse_query');
function firmasite_resimlitarif_parse_query($query) {
    global $wp, $wp_rewrite;


    // Is this query for /%post_name%/? Is it main request query?
    if (isset($query->query['name'])
        && substr($wp->matched_rule, 0, 7) == "([^/]+)"
        && isset($query->query)
        && isset($wp->query_vars)
        && $query->query == $wp->query_vars)
    {
        if (!($post_types = get_query_var("post_type"))) {
            if ($wp_rewrite->permalink_structure == "/%postname%/")
                $post_types = array("post");
            else
                $post_types = array();
        }

        if (is_array($post_types)){ 
            $post_types[] = 'yemek';
            $post_types[] = 'page';
        }


        set_query_var("post_type", $post_types);
    } 
}

用您的帖子类型名称更改“ yemek”。



0

为此,我能想到的最干净的答案(我正在构建一个真正需要自定义帖子类型而没有任何前导标签的插件)是使用自定义页面模板,而不是使用自定义帖子类型。

这样,您的“自定义帖子类型”可以具有诸如/ what之类的url,而不必担心踩页面或发布永久链接。

为此,我最终做了以下工作:

  • 在我的插件中添加自定义页面模板
  • 设置页面模板,以便可以在页面编辑器中选择它
  • 创建仅针对我的页面模板显示的自定义元框

这使我能够:

缺点

当然,尽管这不会踩页面或发布链接,但确实有一些明显的缺点。

没有档案 您将没有档案(如果需要的话),尽管可以通过创建另一个页面模板以使用自定义模板绘制所有页面的档案来解决。

在Pages下管理在 管理员中,没有将所有帖子类型分组在一起的漂亮的左侧导航栏。

这可以通过在页面列表中添加过滤器(让您按使用的页面模板进行过滤),显示新列中使用的任何页面模板等方式部分解决。


话虽这么说,我想要的东西不会引起用户怀疑为什么他们创建了一个新的自定义页面并发现他们无法再访问正常页面或新的自定义页面导致他们网站上的现有页面消失了。

我知道这不是一个真正的解决方案,但它是满足我的需求的替代方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.