如何用固定链接中的自定义分类替换自定义帖子类型

时间:2020-03-21 作者:Emma Expat

我的Url结构为http://domain.com/hospital/hospitalname (此处hospital是自定义帖子类型,hospitalname是注册的业务用户)我想将Url结构更改为http://domain.com/cityname/hospitalname 我有一个税种我的“城市”我应该如何改变永久性的结构。如果我使用下面的代码,城市taxonmy将在自定义结构上显示为标记,或者是否有任何简单的替代方法来实现这一点。请告知。

function wpse_modify_taxonomy() {
    $city_args = get_taxonomy( \'cities\' );
    \'rewrite\' => true,
    \'hierarchical\' => true 

    register_taxonomy( \'cities\', (array) $city_args );
}

add_action( \'init\', \'wpse_modify_taxonomy\', 11 );


add_filter(\'post_link\', \'cities_permalink\', 10, 3);
add_filter(\'post_type_link\', \'cities_permalink\', 10, 3);

function cities_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, \'%cities%\') === FALSE) return $permalink;

        // Get post
        $post = get_post($post_id);
        if (!$post) return $permalink;

        // Get taxonomy terms
        $terms = wp_get_object_terms($post->ID, \'cities\');   
        if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
        else $taxonomy_slug = \'\';

    return str_replace(\'%cities%\', $taxonomy_slug, $permalink);
}   

1 个回复
SO网友:simongcc

WordPress是一个基于查询的系统,您首先需要了解如果使用permalinks和http://domain.com/hospital/hospitalname 提交,WP内部分析如下

发布类型=医院,然后创建查询进行查找。其他链接也是如此,例如http://domain.com/cityname/hospitalname

自定义重写开始工作之前的假设。假设您knowunderstand post typetaxonomy setup. 因为在发布类型和分类设置时。参数决定如何rewrite pathquery_var 将进行设置。

如果,在case中,帖子类型和分类是由plugins, 通过someone else 而是你自己。有必要找出,这是无法猜测的,因为在设置时,自定义参数可能正在更改默认名称。你的情况是这样的。如果您试图通过猜测和假设名称与看起来的名称相同来进行测试,这将浪费时间。

以下示例基于asker在讨论中的信息。它可以帮助任何在理解重写方面苦苦挣扎的人。

了解what taxonomy exists

add_action( \'init\', \'ws361150_debug_test\' );
function ws361150_debug_test() {
    // please comment/uncomment the debug output needed

    // get an array list of available taxonomies name
    // var_dump(get_taxonomies());

    // get an array list of available taxonomies name => object pair
    // var_dump(get_taxonomies( [], \'objects\'));

    // get a specific object (include assoicated post type name)
    // var_dump(get_taxonomy( \'towns\' ));
}

// ... reference result
// ["countries"]=> string(9) "countries" 
// ["cities"]=> string(6) "cities" 
// ...
找到what post type the taxonomy(默认或自定义)为associated to
  • 什么是重写标记,什么是查询变量
    // taxonomy example
    // object(WP_Taxonomy)[1329]
    //   public \'name\' => string \'towns\' (length=5) // taxonomy slug
    //   ...
    //   public \'public\' => boolean true
    //   public \'publicly_queryable\' => boolean true // http://example/?xxxxx= is allowed
    
    //   // post type associated with this taxonomy
    //   public \'object_type\' => 
    //     array (size=1)
    //       0 => string \'post\' (length=4)
    //   public \'rewrite\' => 
    //     array (size=4)
    //    ...
    //       \'slug\' => string \'towns\' (length=5) // rewrite tag is %towns%
    //   public \'query_var\' => string \'towns\' (length=5) // http://example/?towns=
    
    // some taxonomy\'s arguments, it is better view it in formatted form
    // the taxonomy slug is missed in the discussion, so not sure which slug it means, but probably countries because the query_var is countries
    // ["object_type"]=> array(1) { 
    //  [0]=> string(13) "sp_categories" // linked to post type sp_categories
    // } 
    // ["rewrite"]=> array(4) { 
    //  ["slug"]=> string(7) "country" // rewrite is /%country%/
    // } 
    // ["query_var"]=> string(9) "countries" // means http://example.com/?countries= is allowed
    
    // taxonomy \'cities\' arguments
    // ["cities"]=> object(WP_Taxonomy)#2622 (26) { 
    //  ["name"]=> string(6) "cities" // slug is cities
    // ... missed in the discussion
    
    了解custom post type
    • 什么是重写标记,什么是查询变量
      add_action( \'init\', \'ws361150_debug_test_pt\' );
      function ws361150_debug_test_pt() {
          // please comment/uncomment the debug output needed
          // export an array list of all post types list
          var_dump( get_post_types() );
      
          // debug view one post type object by the following method
          $post_types = get_post_types( [], \'objects\' );
          var_dump($post_types[\'post\']); // put in the post type slug
      }
      
      // object(WP_Post_Type)[963]
      //   public \'name\' => string \'post\' (length=4) // post type slug
      //   ...
      //   public \'publicly_queryable\' => boolean true
      //   public \'query_var\' => boolean false
      //   public \'rewrite\' => boolean false // for post it is off, the settings is similar to taxonomy, if slug is set the rewrite is /%specified_slug%/, if true, it is by default /%post_slug%/, so that by default \'post\' is http://example.com/post-name/ instead of http://example.com/post_slug/post-name/
      
      有许多方法需要完成,这里显示了两个方法,一个是重写,另一个是手动修改查询。我已经用示例帖子类型测试了这两种方法,并通过将它们应用到主题函数中完美地工作。php请不要同时放置方法1和方法2,因为只有一种方法建议用于成功的测试。在方法1中,add_permastructadd_rewrite_rule 已使用。

      add\\u permastruct-除了settings > Permalinks 在WordPress中,如果重写标记已注册,如分类法和帖子类型,则可以使用它创建自定义URL结构,添加自定义重写规则-添加自定义重写正则表达式以匹配查询URL,在某些情况下,需要执行自定义规则来执行任务

      // objective: http://domain.com/cityname/hospitalname
      // post type: \'hospital\', assumed the rewrite tag is \'%hospital%\'
      // taxonomy: \'cities\', assumed the rewrite tag is \'%cities%\' and it is associated with hospital, otherwise, it will not work
      add_action( \'init\', \'ws365575_taxonomy_rewrite1\' );
      function ws365575_taxonomy_rewrite1() {
          // optional settings as the 3rd argument for add_permastruct
          // default
          $args = array(
              // \'with_front\'  => true,
              // \'ep_mask\'     => EP_NONE,
              // \'paged\'       => true,
              // \'feed\'        => true,
              // \'forcomments\' => false,
              // \'walk_dirs\'   => true,
              // \'endpoints\'   => true,
          );
      
          // this will need to flush the permalink cache to be effective
          // add to $wp_rewrite->extra_permastructs
          add_permastruct( \'cities_with_hospitals\', "%cities%/%hospital%", $args );
      }
      
      // objective: http://domain.com/hospitalname
      // post_type: \'hospital\', assumed the query vars is \'%hospital%\'
      // the top option tells WP to match it in higher priority before it is being regarded as not found
      add_action( \'init\', \'ws365575_taxonomy_rewrite2\' );
      function ws365575_taxonomy_rewrite2() {
          // the rule is copied from originally registered post types \'hopsital\' part and modify by following page post type\'s rewrite
      
          add_rewrite_rule(\'(.?.+?)/page/?([0-9]{1,})/?$\', \'index.php?hospital=$matches[1]&paged=$matches[2]\', \'top\');
          add_rewrite_rule(\'(.?.+?)?(:/([0-9]+))?/?$\', \'index.php?hospital=$matches[1]&page=$matches[2]\', \'top\');
      
          // because the above will override the priority, to avoid page cannot be loaded and become 404, manually add once more
          add_rewrite_rule(\'(.?.+?)/page/?([0-9]{1,})/?$\', \'index.php?pagename=$matches[1]&paged=$matches[2]\', \'top\');
          add_rewrite_rule(\'(.?.+?)?(:/([0-9]+))?/?$\', \'index.php?pagename=$matches[1]&page=$matches[2]\', \'top\');
      }
      
      **设置上述代码后,需要刷新permalink缓存。请参考以下注释**

      要确认注册的标记是否正确,可以转储$wp\\u重写全局变量。

      // the following is for optional for debug
      add_action( \'init\', \'ws365575_confirm_wp_rewrite\' );
      function ws365575_confirm_wp_rewrite() {
          global $wp_rewrite;
      
          // if xdebug is not installed, it is recommended to view in source
          var_dump($wp_rewrite);
      
          exit(); // break the code to read
      }
      
      方法2:如果访问链接,请立即手动修改查询(高级)http://domain.com/hospitalname 并使其等效于http://domain.com/hospital/hospitalname 缺少post type 信息,它需要一些逻辑来分析和工作。

      过滤器request 提供对任何查询的早期控制,并且适合执行此工作。虽然有效,但请注意,这取决于教育WP进行分析的程度。因此,必须对不同的情况进行大量测试和深入思考,例如similar name, 猜错了,异常处理。

      ***它不会吹WP,最多返回404或错误页面。以下内容通过放置在theme的函数中,在自定义帖子类型上进行测试。php

      add_filter( \'request\', \'ws361150_custom_request_query\' );
      function ws361150_custom_request_query( $query ) {
          if ( isset( $_SERVER[\'HTTP_HOST\'] ) ) {
              // build the URL in the address bar
              $requested_url  = is_ssl() ? \'https://\' : \'http://\';
              $requested_url .= $_SERVER[\'HTTP_HOST\'];
              $requested_url .= $_SERVER[\'REQUEST_URI\'];
          }
      
      
          if( url_to_postid( $_SERVER[\'REQUEST_URI\']) > 0 ) {
              // if something is found priorly, nothing to do, suppose something exists
      
              return $query;
          } else {
              // must think of a logic and test thoroughly before production
      
              // manual setup the post query by guess            
              // check if rewrite slugs match original settings (spelling...etc)
              if( $search_ID = url_to_postid( \'hospital\' . $_SERVER[\'REQUEST_URI\']) > 0 ) {
                  // setup query based on source code, if match by test
      
                  // check if post type name match settings
                  $query[\'post_type\'] = \'hospital\';
                  $query[\'hospital\'] = $query[\'name\'];
      
                  // var_dump($query);
                  // exit();
                  return $query;
              }
          }
      
          return $query; // untouched
      }
      
      它看起来像一个简单的代码,开销更小,它在很大程度上依赖于提供的测试逻辑。

      重置永久链接(刷新缓存)

      提醒,每当更改重写段塞或规则时,都需要刷新缓存。最简单的方法是settings > permalinks 然后单击保存。如果不更新缓存,它可能会坚持旧的设置,并浪费时间进行测试。

      设置URL后需要进行其他工作,然后需要使用post_linkpost_type_link 钩子以更改的链接get_permalinks()get_post_permalink() 获取链接。然后链接将反映在前端或后期编辑页面上,因为WP不会自动执行此操作。

相关推荐

Wp_Term_Taxonomy.Parent引用了什么?

我最初的想法是,它引用了另一种分类法(即wp_term_taxonomy.parent 到wp_term_taxonomy.term_taxonomy_id). Corcel这样的怪物built under this assumption. 然而,我done some digging 大多数信息似乎表明它实际上引用了wp_terms.term_id. 在Corcel的案例中,我认为这种巧合是可行的——WordPress将设置term_id 以及term_taxonomy_id 到相同的值。如果您弄乱了数据