带分类的CPT的永久链接

时间:2018-04-19 作者:Atimmy

[Edited]

我把网站的目的改成了语言学习网站。

现在,CPT设置如下:

{ Language } - { Subject }

<英语口语(slug:英语口语)
  • 英语写作(英语写作)
  • 英语阅读(英语口语)
  • 英语写作(英语写作)

  • Single CPT setup

    因为每个CPT可能有不同的分类法……所以最好考虑代码。

    假设:CPT“英语口语”有一个自定义的“口语任务”(口语任务)分类法,术语为“任务1”、“任务2”、“任务3”。但是:CPT“英语写作”根本没有分类学。

    单个CPT post项目所需的URL:

    With custom taxonomy terms:

    • www.domain。com/{language}/{subject}/{term slug}/{custom question id}/{post name}
    • 例如www.domain。com/英语/口语/口语-1/32/诸如此类诸如此类

      Without custom taxonomy terms:

      • www.domain。com/{语言}/{主题}/{自定义问题id}/{帖子名}
      • 例如www.domain。com/英语/写作/32/诸如此类诸如此类

        The URL rewrite part for Single CPT is not a problem for me now thanks to your teaching and genius code provided in the new answer

        我正在努力重写下面的CPT归档页面:

        <小时>

        CPT Archive setup

        我正在尝试使用以下URL设置创建自定义CPT存档模板:

        www.domain。com/{语言}/{主题}例如www.domain。com/英语/口语

        www.domain。com/{语言}/{主题}/{术语段塞}

        示例1。www.domain。com/english/speaking(不是列出所有帖子,而是将其默认设置为“speaking-1”)

      • ex2。www.domain。com/english/speaking/speaking-1(仅在“speaking-1”下列出帖子)示例3。www.domain。com/english/speaking/speaking-2(仅在“speaking-2”下列出帖子)
      -----------------------------------

      在中[archive-english-speaking.php] , 我有以下代码:

      // use add_rewrite_rule in funcitons; query_vars "task" is terms of speaking-task taxonomy
      global $wp_query;
      $task_no = $wp_query->query_vars[\'task\'];
      
      
      if (preg_match("/[1-6]/", $task_no)) {
        $task = ( \'speaking-\' . $task_no );
      } else {
        $task_no = ( \'1\' );
        $task = ( \'speaking-\' . $task_no );
      }
      
      $posts_per_page = 10;
      
      
      $the_query = new WP_Query( array( 
        \'post_type\' => \'english-speaking\',
        \'taxonomy\' => \'speaking-task\',
        \'term\' => $task,
        /*\'paged\' => $paged,
        \'posts_per_page\' => $posts_per_page,*/
        \'orderby\'   => \'meta_value_num\',
        \'meta_key\' => \'wpcf-question-id\',
        \'order\'   => \'ASC\', /* ASC/DESC */
         ) );
      
      -----------------------------------

      在中[functions.php] , 我有以下代码:

      function custom_rewrite_tag() {
          //taxonomy speaking-task =?
          add_rewrite_tag(\'%task%\', \'([^/]*)\');
      }
      add_action(\'init\', \'custom_rewrite_tag\', 10, 0);
      
      
      
      // Custom Question ID from custom field
      function cqid() {
          $cqid = get_post_meta( get_the_ID(), \'wpcf-question-id\', true );
          return $cqid;
      }
      
      
      function my_questions_cpt_list() {
          return [
          // Format: POST_TYPE   => QUESTION_SUBJECT_SLUG
              \'english-listening\' => \'listening\',
              \'english-speaking\' => \'speaking\',
              \'english-reading\' => \'reading\',
              \'english-writing\' => \'writing\',
              // Add more items as needed, or if and when you register another CPT
              // for questions.
          ];
      }
      
      
      add_action( \'init\', \'my_questions_cpt_add_rewrite_rules\' );
      function my_questions_cpt_add_rewrite_rules() {
      
      
      // Archive Page 
      add_rewrite_rule( \'^english/speaking/?$\',\'index.php?post_type=english-speaking&taxonomy=speaking-task&task=$matches[1]\', \'top\' );
      add_rewrite_rule( \'^english/speaking/([^/]*)/?$\',\'index.php?post_type=english-speaking&taxonomy=speaking-task&task=$matches[1]\', \'top\' );
      
      
      //
      $cpt_list = my_questions_cpt_list();
      foreach ( $cpt_list as $post_type => $q_subject ) {
          if ( empty( $post_type ) ) {
              continue;
          }
      
          if ( ! $s = preg_quote( $q_subject ) ) {
              continue;
          }
      
      
          add_rewrite_rule(\'^english/(\' . $s . \')/(\\d+)/(\\d+)/([^/]+)/?\',\'index.php?\' . $post_type . \'=$matches[4]\',\'top\');
      }
      }
      
      
      
      add_filter( \'post_type_link\', \'my_questions_cpt_custom_permalink\', 10, 2 );
      function my_questions_cpt_custom_permalink( $permalink, $post ) {
          $taxonomy = \'speaking-task\';
          $cpt_list = my_questions_cpt_list();
      
      if ( false === strpos( $permalink, \'?\' ) &&
      $post && isset( $cpt_list[ $post->post_type ] ) ) {
          $cats = get_the_terms( $post, $taxonomy );
          if ( $cats && ! is_wp_error( $cats ) ) {
              // If assigned to multiple tasks (or categories), then we use just
              // the first task/term.
      
              $cat_id = $cats[0]->slug; //term_id
              $task = $cat_id[strlen($cat_id)-1];
              $cqid = cqid();
      
              $s = $cpt_list[ $post->post_type ];
              $permalink = home_url( \'english/\' . $s . \'/\' . $task . \'/\' . $cqid . \'/\' . $post->post_name . \'/\' );
              $permalink = user_trailingslashit( $permalink, \'single\' );
          }
      }
      
      return $permalink;
      }
      
      -----------------------------------

      @Sallyth以上代码仅限于我的编程级别,我使用了您的第一个答案并对其进行了修改。。。这是一种工作在本地主机,但存档url得到404或空白页时,我把它移动到在线托管服务器。。。

    2 个回复
    最合适的回答,由SO网友:Sally CJ 整理而成

    (更新/新答案)

    因此,这里我将直接讨论您需要的代码:(但一定要阅读原始答案的更新版本)

    注册CPT并设置正确的重写slug

    register_post_type( \'english-speaking\', array(
        \'label\' => \'English Speaking\',
        \'public\' => true,
        \'rewrite\' => array(
            \'slug\' => \'english/speaking/%speaking_task%/%question_id%\',
        ),
        // Other args here.
    ) );
    
    这是针对“英语写作”CPT的,它不属于任何分类法:

    register_post_type( \'english-writing\', array(
        \'label\' => \'English Writing\',
        \'public\' => true,
        \'rewrite\' => array(
            \'slug\' => \'english/writing/%question_id%\',
        ),
        // Other args here.
    ) );
    
    注册自定义分类法“口语任务”

    register_taxonomy( \'speaking-task\', array( \'english-speaking\' ), array(
        \'label\' => \'Speaking Tasks\',
        \'public\' => true,
        \'rewrite\' => array(
            \'slug\' => \'english/speaking\',
        ),
        // Other args here.
    ) );
    
    确保重写slug 设置为english/speaking.

    “英语”档案可访问:

    • http://example.com/english/speaking

    • http://example.com/english/speaking/{SPEAKING TASK SLUG}

      add_rewrite_tag( \'%question_id%\', \'(\\d+)\' );
      add_rewrite_tag( \'%speaking_task%\', \'([^/]+)\' );
      
      添加替换自定义重写标记的代码
      add_filter( \'post_type_link\', \'my_filter_questions_post_type_link\', 10, 2 );
      function my_filter_questions_post_type_link( $post_link, $post ) {
          // Replaces/rewrites %question_id% in the permalink.
          if ( false !== strpos( $post_link, \'%question_id%\' ) ) {
              $id = get_post_meta( $post->ID, \'wpcf-question-id\', true );
      
              // A default value is necessary, and the value has to be a 0.
              $id = $id ? $id : \'0\';
      
              $post_link = str_replace( \'%question_id%\', $id, $post_link );
          }
      
          // Replaces/rewrites %speaking_task% in the permalink.
          if ( false !== strpos( $post_link, \'%speaking_task%\' ) ) {
              // A default value is necessary, but the term/category doesn\'t need to
              // actually exists. So you could, for example, use \'all\' as the value.
              $slug = \'uncategorized\';
      
              $cats = get_the_terms( $post, \'speaking-task\' );
              if ( $cats && ! is_wp_error( $cats ) ) {
                  $slug = $cats[0]->slug;
              }
      
              $post_link = str_replace( \'%speaking_task%\', $slug, $post_link );
          }
      
          return $post_link;
      }
      
      刷新重写规则如果您不知道如何刷新规则,请参阅我的其他答案。。

      使用get_query_var() 检索重写标记值get_query_var( \'question_id\' ) 对于%question_id%

    • get_query_var( \'task_slug\' ) 对于%task_slug%


      • 完整的示例代码is available here. :)

        如果使用插件注册post type, 您可以过滤(设置/更改)重写slug 通过register_post_type_args 过滤器,如下所示:

        add_filter( \'register_post_type_args\', \'my_filter_post_type_args\', 10, 2 );
        function my_filter_post_type_args( $args, $post_type ) {
            if ( ! isset( $args[\'rewrite\'] ) ) {
                $args[\'rewrite\'] = array();
            }
        
            if ( \'english-speaking\' === $post_type ) {
                $args[\'rewrite\'][\'slug\'] = \'english/speaking/%speaking_task%/%question_id%\';
            } elseif ( \'english-speaking\' === $post_type ) {
                $args[\'rewrite\'][\'slug\'] = \'english/writing/%question_id%\';
            }
        
            return $args;
        }
        
        同样,如果您使用插件注册custom taxonomy, 您可以过滤(设置/更改)重写slug 通过register_taxonomy_args 过滤器,如下所示:

        add_filter( \'register_taxonomy_args\', \'my_filter_taxonomy_args\', 10, 2 );
        function my_filter_taxonomy_args( $args, $taxonomy ) {
            if ( ! isset( $args[\'rewrite\'] ) ) {
                $args[\'rewrite\'] = array();
            }
        
            if ( \'speaking-task\' === $taxonomy ) {
                $args[\'rewrite\'][\'slug\'] = \'english/speaking\';
            }
        
            return $args;
        }
        
        您可能需要设置较低的优先级;i、 e.更改1011 或更高的值(数字)&mdash;数字越大,优先级越低,而数字越低,优先级越高。

        或者,在没有自定义编码的情况下,如果插件允许您手动设置自定义帖子类型或分类的重写段塞,则只需使用适当的框/字段输入适当的重写段塞即可。=)

    SO网友:Sally CJ

    (更新/新答案)

    For the original question

    我改变了原来的答案,因为实际上有一种更简单的解决方案(无需使用add_rewrite_rule() 函数,或挂接到parse_request 过滤器)在实现此permalink结构时(针对您的“问题”CPT):

    • /{SLUG}/question/{TASK ID}/{POST SLUG}

      • /science/question/2/science-question-1
      • /math/question/4/math-question-1
      • /english/question/4/english-question-1

      So how to achieve that?

      当您通过注册“问题”CPT时register_post_type() 函数,设置重写slug{SLUG}/question/%task_id% 哪里{SLUG} 是否有任何段塞,如science, math, 和english.

      register_post_type( \'science-question\', array(
          \'label\' => \'Science Questions\',
          \'public\' => true,
          \'rewrite\' => array(
              // The rewrite slug. You can change \'science\' to whatever you like.
              \'slug\' => \'science/question/%task_id%\',
          ),
          // Other args here.
      ) );
      
      register_post_type( \'math-question\', array(
          \'label\' => \'Math Questions\',
          \'public\' => true,
          \'rewrite\' => array(
              // The rewrite slug. You can change \'math\' to whatever you like.
              \'slug\' => \'math/question/%task_id%\',
          ),
          // Other args here.
      ) );
      
      然后,对于自定义分类法“任务”(通过register_taxonomy() 函数),设置分类slugtask 比如这个例子:

      // Set the slug to \'task\'.
      register_taxonomy( \'task\', array( \'{POST TYPE}\', \'{POST TYPE}\', ... ), array(
          \'label\' => \'Tasks\',
          \'public\' => true,
          // Other args here.
      ) );
      
      (The{POST TYPE} 可能是science-question, math-question, 等等)

      接下来,添加此代码,它将注册自定义重写标记%task_id%:

      add_rewrite_tag( \'%task_id%\', \'(\\d+)\' );
      
      并添加此代码,该代码将替换%task_id% post permalink中的标记:

      // Replaces %task_id% in the permalink (i.e. $post_link).
      add_filter( \'post_type_link\', \'my_filter_questions_post_type_link\', 10, 2 );
      function my_filter_questions_post_type_link( $post_link, $post ) {
          if ( false !== strpos( $post_link, \'%task_id%\' ) ) {
              $cats = get_the_terms( $post, \'task\' );
              $cat_id = 0;
      
              // If the post was assigned to at least one "task" category.
              if ( $cats && ! is_wp_error( $cats ) ) {
                  $cat_id = $cats[0]->term_id;
              }
              // Else, /{SLUG}/question/0/{POST SLUG} should work well. =) But of
              // course, all "question" CPT posts should be assigned to *at least*
              // one "task".
      
              $post_link = str_replace( \'%task_id%\', $cat_id, $post_link );
          }
      
          return $post_link;
      }
      
      完整示例代码is available here. :)

      Don\'t forget to flush the rewrite rules!

      这是必要的,方法如下:只需转到“永久链接设置”页面。仅此而已。

      但如果未刷新重写规则(您可以访问“问题”页面进行确认),则在“永久链接设置”页面上,单击“保存更改”按钮,无需进行任何更改。

      How to get the value of task_id

      使用get_query_var( \'task_id\' ). 示例:

      $task_id = get_query_var( \'task_id\' );
      $term = get_term( $task_id );
      
      PS:我知道问题已经改变了,但我更新了这个答案,因为它可以帮助其他人

    结束

    相关推荐

    How to replace permalinks

    我已将wordpress项目导出并导入live server。现在的问题是,我将permalink结构作为“localhost”格式。当我单击网站中的任何链接时,它会将我重定向到localhost。我怎样才能改变这一点?我的htaccess文件如下所示<IfModule mod_rewrite.c> RewriteEngine On RewriteBase /myproject/ RewriteRule ^index\\.php$ - [L] RewriteCo