自定义帖子类型类别、分类和URL重写问题

时间:2020-11-19 作者:Reza

我是WordPress的新手,正在开发一个产品种类丰富的网站。我想创建一个自定义帖子类型来添加一系列产品。我将展示我正在努力实现的目标,然后阐述我所面临的问题。

Here are my requirements:

<我需要按以下方式对我的产品进行分类brandfunctionality 它需要翻译为:

by brand:

example.com/products/sub-category/product-name
eg. domain.com/products/toshiba/toshiba-E-Studio-2518A

by functionality:

example.com/products/functionality-category/product-name
eg. domain.com/products/color-printer/toshiba-E-Studio-2518A
正如您在上面的示例中所看到的,产品被分类在多个类别下。

我需要这些类别和分类中的每一个都有一个存档页面(或任何包含所有相关帖子的页面)

eg. domain.com/products/toshiba/ -> show all toshiba products

eg. domain.com/products/color-printer/ -> show all color printers

eg. domain.com/products/ -> show all products

到目前为止,我已经尝试了:

首先,我尝试使用CPT ui, 我在自定义帖子中使用了类别,解决了50%的问题。但是,类别的URL slug不能与自定义post slug相同Followed this article 老实说,还有很多问题我在这个问题上经历了将近一年的艰难时期week 现在真的找不到解决方法,所以我希望能得到一些帮助。

谢谢

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

欢迎使用WPSE。

这可以很直接地解决。

注册自定义帖子类型products

  • 根据模板层次结构和WordPress标准,为您的自定义帖子类型注册两个分类法(品牌和功能)
  • 为WordPress提供正确的模板,刷新您的重写规则(不能跳过,但很容易)
    1. Step 1

      在主题函数中注册自定义帖子类型。php或类似的插件文件:

      <?php
      /* Register Custom Post Type \'products\' */
      function wpse_register_custom_post_type_products(){
      
          // Custom Post Type Name
          $cpt_name = \'products\';
          // CPT Features
          // the fields you need
          $cpt_features = array(
              \'title\',
              \'excerpt\',
              \'revisions\',
              \'thumbnail\'
          );
          // Slug / name of the archive /product/my-product/
          $cpt_slug = \'products\';
      
          $labels = array(
              \'name\'                      =>  __(\'Products\', \'textdomain\'),
              \'singular_name\'             =>  __(\'Product\', \'textdomain\'),
              \'menu_name\'                 =>  __(\'Products\', \'textdomain\'),
              \'name_admin_bar\'            =>  __(\'Products\', \'textdomain\'),
              // Archive page name
              \'all_items\'                 =>  __(\'Products\', \'textdomain\'),
              \'add_name\'                  =>  __(\'Add new products\', \'textdomain\'),
              \'add_new_item\'              =>  __(\'Add new products\', \'textdomain\'),
              \'edit\'                      =>  __(\'Edit products\', \'textdomain\'),
              \'edit_item\'                 =>  __(\'Edit product\', \'textdomain\'),
              \'new_item\'                  =>  __(\'New product\', \'textdomain\'),
              \'view\'                      =>  __(\'View products\', \'textdomain\'),
             \'view_item\'                  =>  __(\'View product\', \'textdomain\'),
              \'search_items\'              =>  __(\'Search products\', \'textdomain\'),
              \'parent\'                    =>  __(\'Parent product\', \'textdomain\'),
              \'not_found\'                 =>  __(\'No product found\', \'textdomain\'),
              \'not_found_in_trash\'        =>  __(\'No product found in trash\', \'textdomain\')
      );
      
          /* ------------------------------------------ End of Edit */
          $args = array(
              \'labels\'                =>  $labels,
              \'public\'                =>  true,
              \'publicly_queryable\'    =>  true,
              \'exclude_from_search\'   =>  false,
              \'show_in_nav_menus\'     =>  true,
              \'show_ui\'               =>  true,
              \'show_in_menu\'          =>  true,
              \'show_in_admin_bar\'     =>  true,
              \'show_in_rest\'          =>  true,
              \'menu_position\'         =>  21,
              \'menu_icon\'             =>  \'dashicons-marker\', // Dashicon
              \'can_export\'            =>  true,
              \'delete_with_user\'      =>  false,
              \'hierarchical\'          =>  false,
              \'has_archive\'           =>  true,
              \'query_var\'             =>  true,
              \'capability_type\'       =>  \'post\',
              \'map_meta_cap\'          =>  true,
              // \'capabilities\'       => array(),
              \'rewrite\'               =>  array(
                  \'slug\'      => $cpt_slug,
                  \'with_front\'=> true,
                  \'pages\'     => true,
                  \'feeds\'     => false
              ),
              \'supports\'      => $cpt_features
          );
          register_post_type($cpt_name, $args);
      }
      add_action(\'init\', \'wpse_register_custom_post_type_products\', 21);
      ?>
      
      上述代码的作用是:

      add\\u action在WordPress循环中添加一个新操作,我们在后端得到一个新的post类型,名为;产品最后一个参数;21英寸;是优先级(在后端的位置[上|下]),在后端显示帖子类型的时间/位置

    Step 2

    注册分类法(类别或标记)。如果您愿意;“标签”;而不是类别>;然后将层次结构更改为false。

    以下代码注册了taxonomy 到您的自定义帖子类型(产品类别和子类别,我认为这是您所追求的)。

    <?php
    /* Register taxonomy / Product brands*/
    function wpse_register_taxonomy_brands() {
        // Where to register the Taxonomy > which post type
        $cpt_name = \'products\';
        // Taxonomy Name
        $cpt_slug = \'brands\';
    
        // Taxonomy Labels
        $labels = array(
            \'name\'                      =>  __(\'Brands\', \'textdomain\'),
            \'singular_name\'             =>  __(\'Brand\', \'textdomain\'),
            \'search_items\'              =>  __(\'Search brands\', \'textdomain\'),
            \'popular_items\'             =>  __(\'Popular brands\', \'textdomain\'),
            \'all_items\'                 =>  __(\'All brands\', \'textdomain\'),
            \'parent_item\'               =>  null,
            \'parent_item_colon\'         =>  null,
            \'edit_item\'                 =>  __(\'Edit brand\', \'textdomain\'),
            \'update_item\'               =>  __(\'Update brand\', \'textdomain\'),
            \'add_new_item\'              =>  __(\'Add new brand\', \'textdomain\'),
            \'new_item_name\'             =>  __(\'New brand\',\'textdomain\'),
            \'separate_items_with_commas\'=>  __(\'Separate brands\', \'textdomain\'),
            \'add_or_remove_items\'       =>  __(\'Add or remove brands\', \'textdomain\'),
            \'choose_from_most_used\'     =>  __(\'Choose from most used brands\', \'textdomain\'),
            \'not_found\'                 =>  __(\'No brands found\', \'textdomain\'),
            \'not_found__in_trash\'       =>  __(\'No brands found in trash\', \'textdomain\'),
            \'menu_name\'                 =>  __(\'Brands\', \'textdomain\')
    );  
    
        // Taxonomy Args
        $args = array(
            \'hierarchical\'              =>  true,
            \'labels\'                    =>  $labels,
            \'show_ui\'                   =>  true,
            \'show_admin_column\'         =>  true,
           \'update_count_callback\'      =>  \'_update_post_term_count\',
           \'query_var\'                  =>  true,
                \'rewrite\'                   => array(
                    \'slug\'  =>  $cpt_slug
            )
        );
    
        register_taxonomy($cpt_slug, $cpt_name, $args);
    }
    add_action(\'init\', \'wpse_register_taxonomy_brands\');
    
    到目前为止,一切顺利。您现在应该有一个名为“的自定义帖子类型”;“产品”;和分类法“;品牌;。

    Step 3

    Feed WordPress正确的模板。

    如果你不知道从哪里开始,这部分可能会很棘手。这就是我们在这里的原因:

    您需要使用正确的挂钩,即template_include 否则就不行了。Not "E;template\\u redirect“;,这是一个不同的钩子。

    为了在WordPress中检查/返回正确的模板,您需要以下内容:

    <?php
    
    // Template logic
    function wpse_custom_post_type_template_include($original_template) {
    
        // Archive page > yourdomain.com/products/ or search results page
        if(is_post_type_archive(\'products\')||(is_search() && $_GET[\'post_type\']==\'products\')) {
            // Here we check if a file exists in the current active theme folder, if not look in a plugin directory.
            if(file_exists(get_template_directory() . \'/archive-products.php\')) {
                return get_template_directory() . \'/archive-products.php\';
            } else {
                // Look in a plugin directory
                return plugin_dir_path(__DIR__) . \'templates/archive-products.php\';
            }
        // Same for Taxonomy
        } elseif (is_tax(\'brands\')) {
            if(file_exists(get_template_directory(). \'/taxonomy-brands.php\')){
                return get_template_directory(). \'/taxonomy-brands.php\';
            } else {
                return plugin_dir_path(dirname(__FILE__)).\'templates/taxonomy-brands.php\';
        }
        // Same for single product page
        } elseif(is_singular(\'products\')) {
            if(file_exists(get_template_directory() . \'/single-products.php\')) {
                return get_template_directory() . \'/single-products.php\';
            } else {
                return plugin_dir_path(__DIR__) . \'templates/single-products.php\';
            }
        }
        return $original_template;
    }
    add_action(\'template_include\', \'wpse_custom_post_type_template_include\');
    ?>
    
    要记住的重要事项:

    功能get_template_directory_uri() 返回主题的URL,but this is wrong - we don\'t want that.

    我们需要get_template_directory (没有uri!!!)这是返回文件路径的正确函数。

    功能get_template_directory_uri() 返回url,但我们需要路径。因此,请始终坚持使用get\\u template\\u directory()。

    根据上面的代码,您的插件文件夹结构must 有点像:

    Folder and template names

    这将使您的插件中有一个模板(用于默认发货),并且可以被主题覆盖。

    现在,您应该能够在后端创建产品,为其指定类别和/或子类别。

    你的问题最重要的是;分类法-{$taxonomy}。php“;模板工作,负责返回自定义帖子类型的分类法(品牌/功能)的正确模板。

    熟悉;模板层次结构;在WordPress中查找分类法-{$taxonomy}。php在以下页面:

    WordPress template hierarchy overview

    templates/archive-products.php

    <?php get_header(); ?>
    <div class="container">
        <div class="row">
            <main class="col">
                <?php
                   
                   $query_args = array(
                       \'post_type\' => \'products\',
                       \'post_status\' => \'publish\',
                       \'posts_per_page\' => -1,
                       \'order\' => \'ASC\',
                       \'orderby\' => \'name\'
                   );
    
                   $loop = new WP_Query( $query_args );
    
                   $html = \'\';
                   if ( $loop->have_posts() ) {
                       while ( $loop->have_posts() ) : $loop->the_post();
    
                       // Start of output, like:
                       $html .= \'<h2>\'.get_the_title().\'</h2>\';
                       $html .= \'<p>\'.get_the_excerpt().\'</p>\';
                       endwhile;
                       // reset the query
                       wp_reset_postdata();
                       // Spit the html out
                       echo $html;
                   } else {
                       // No posts / products found
                       echo \'<div class="alert alert-warning"><p>\'__(\'No products found\' \'textdomain\').\'</p></div>\';
                   }
                ?>
            </main>
        </div>
    </div>
    <?php get_footer(); ?>
    

    templates/taxonomy-brands.php

    <?php get_header(); ?>
    <div class="container">
        <div class="row">
            <main class="col">
                <?php
    
            $current_term = get_query_var(\'term\');
    
            $query_args= new WP_Query( array(
                \'post_type\' => \'products\',
                \'tax_query\' => array(
                    array (
                        \'taxonomy\' => \'brands\',
                        \'field\' => \'slug\',
                        \'terms\' => $current_term,
                    )
                ),
            ));
    
            while ( $query_args->have_posts() ) :
            $query_args->the_post();
            // Show Posts ...same as in archive-products.php, generate your markup here..
            endwhile;
    
            /* Restore original Post Data 
             * NB: Because we are using new WP_Query we aren\'t stomping on the 
             * original $wp_query and it does not need to be reset.
            */
            wp_reset_postdata();
        
       
            ?>
            </main>
        </div>
    </div>
    <?php get_footer(); ?>
    
    在您的情况下,需要注册两个分类法(品牌和功能)。

    因此,除了;“品牌”;,在WP层次结构之后注册第二个分类法(复制第一个分类法的代码、更改名称等,并添加第二个税务模板)。

    进一步阅读请参见此问题:How to query for a custom post type taxonomy

    Step 4

    刷新重写规则。

    在仪表板中,转到>;设置(>);permalinks。已完成。

    Bonus 一开始有时很难找到:

    添加产品帖子后,您可能很难在屏幕上找到正确的链接>;菜单设置。

    Display menus > archive page of custom post type

    如果菜单选项中没有该面板。然后查看右上角,确保显示了该立柱类型。How to find the menu panel

    理论上,这已经完成,您应该能够添加带有品牌和子品牌的产品,并且应该能够在前端输出它们。

    您的不同“;“要求”;是税务查询和模板逻辑中的简单更改,应该可以使用上述给定信息。

    复制;“分类品牌”;代码,将其更改为functionaties,添加第二个模板,名为taxonomy functionaties。php,您就完成了。

    但是,您也可以查看一些挂钩,如:

    在此处输入\\u title\\u(更改标题字段占位符)、wp\\u enqueue\\u脚本(在前端加载一些额外的js或css文件)、admin\\u enqueue\\u脚本(如果要在后端为元盒添加一些js或css文件等…)

    对调试模板也很有帮助:

    插件文件是什么插件查询监视器

    相关推荐

    Problem with permalinks

    我已经更改了类别的基本名称,现在它是“博客”,工作正常。但当我通过/blog/%category%/%postname%/更改结构时。显示404。如果我删除结构中的blog,它会再次工作,但我想使用blog word。问题出在哪里?非常感谢。