如何在WordPress中订购类别?

时间:2009-02-05 21:13:28

标签: wordpress wordpress-theming

我使用wp_list_categories()获取所有类别的列表并生成导航栏。有没有办法按字母排序以特定顺序排序这些类别。

例如:Connect,News&观点,Q& A,Hello Startup,Startup 101 ......

8 个答案:

答案 0 :(得分:6)

如果您不使用类别的“说明”字段,也可以通过在每个“说明”字段中输入一个数字来完成排序,然后根据此编号使用Javascript / jQuery进行排序。

wp_list_categories函数有一个 use_desc_for_title 参数,您可以将其设置为true:

wp_list_categories('use_desc_for_title=1');

类别说明现在设置为生成的html中的<a>标记的title属性。

因此,如果您在说明字段中使用数字,则生成的类别列表可能如下所示:

 <ul id="category_list">
    <li><a href="#" title="3">Category C</a></li>
    <li><a href="#" title="1">Category A</a></li>
    <li><a href="#" title="2">Category B</a></li>  
 </ul>

现在您可以对列表进行排序,例如在document.ready事件中使用jQuery。如果以分层方式使用子类别,请使用如下的递归函数:

$( document ).ready( 
    function() {
       sort_list_recursive( $( '#category_list' ) );
    }
);

function sort_list_recursive( parent ) {
    var lst = parent.children( 'li' );
    lst.sort(
        function( a, b ) {
            var _a = a.getElementsByTagName( 'a' )[0].title;
            var _b = b.getElementsByTagName( 'a' )[0].title;
            return _a > _b ? 1 : -1;
        }
    ).appendTo( parent );
    lst.each( function() {
        $( this ).children( 'ul' ).each( function() {
            sort_list_recursive( $( this ) );
        });
    });
}

N.B。

  • 不要在描述字段中使用0(零),它将被忽略并设置为空
  • 排序之后你可能想要摆脱设置为数字的标题属性,这可以通过jQuery轻松完成。

答案 1 :(得分:4)

大多数主题都没有使用类别的描述。我做的简单解决方法是在描述中使用数字。这里的顶级帖子目前有一些jQuery hack来自这里,它是不需要的。

您也可以添加自定义订单字段。

只是

$categories = get_categories( array(
    'orderby' => 'description',
    'order'   => 'ASC'
) );

答案 2 :(得分:3)

这是内置于wordpress_wp_list_categories

wp_list_categories('orderby=name');

我认为这会帮助你

答案 3 :(得分:3)

技术方法

wordpress核心中的问题是表wp_terms没有term_order列。这意味着,标准wordpress不支持自定义术语顺序。如果您查看此WP database structure,可以找到表格wp_term_relationships。此表负责帖子与分类法(您的类别)之间的关系,此表格有term_order列。

现在,使用简单的SQL语句ALTER TABLE wp_terms ADD term_order INT(11) NOT NULL DEFAULT 0(不要忘记$wpdb->wp_terms变量),您可以向表中添加一列,该列负责您的自定义类别顺序。然后,您可以将自定义类别订单放在wp_term_relationshipswp_terms这两列中。完成所有操作后,您可以加入get_terms_args的过滤器,并将orderby更改为term_order

此处列出了技术方法的所有相关链接:

插件可以为您完成工作

检查我的插件以解决此问题:WordPress Real Categories Management WP RCM 在wp条款表上创建了一个额外的字段term_order。它还带来了许多其他有用的功能,如下面的屏幕截图所示。它允许您以一种很好的方式组织您的wordpress类别。它易于使用,只需拖放您的类别并将其移至特定订单。该插件适用于所有自定义帖子类型

Drag & Drop categories order

从我可以引用的产品说明中。如果你想试试这个插件,还有一个 demo on the plugin page

有很多免费插件

这可以通过wordpress.org插件库中提供的大量免费插件来解决。只需搜索&#34;类别订单&#34;在你的Wordpress仪表板&gt;插件&gt;安装。

答案 4 :(得分:0)

为了未来访客的利益,这是解决这个问题的简单方法:

现在有许多插件可以让您在WordPress中订购类别或其他自定义分类。您可以在WordPress插件目录的“category order” tag page中看到其中一些。我个人可以确认Custom Taxonomy Order NE插件可以完成这项任务。

答案 5 :(得分:0)

我做了几个术语列表。我后来通过自己的订单来称呼它。我是一名PHP初学者。

首先,我在不同的变量中存储每个类别术语的ID:

$terms = get_terms('my_taxonomy', 'hide_empty=0');
        foreach ( $terms as $term ) {
           ${$term->slug} = get_term_by('slug', $term->slug, 'product_cat');
           ${$term->slug.'_array'} = (array)${$term->slug};
           ${$term->slug.'_array_id'} =${$term->slug.'_array'}['term_id'];
      };

然后,我为每个wp_list_categories()创建几个args,使用此变量包含我想要的术语:

      $args = array(
        'taxonomy'     => 'my_taxonomy',
        'orderby'      => 'name',
        'show_count'   => true,
        'pad_counts'   => false,
        'hierarchical' => true,
        'title_li'     => '',
        'hide_empty'   => 0,
        'show_option_all' => 'Show all',
        'exclude'    => array( $term1_array_id, $term2_array_id )
      );

      $args_1 = array(
        'taxonomy'     => 'my_taxonomy',
        'orderby'      => 'name',
        'show_count'   => true,
        'pad_counts'   => false,
        'hierarchical' => true,
        'title_li'     => '',
        'hide_empty'   => 0,
        'exclude'    => array( $term3_array_id, $term4_array_id, $term1_array_id )
      );

      $args_2 = array(
        'taxonomy'     => 'my_taxonomy',
        'orderby'      => 'name',
        'show_count'   => true,
        'pad_counts'   => false,
        'hierarchical' => true,
        'title_li'     => '',
        'hide_empty'   => 0,
        'exclude'    => array( $term1_array_id, $term4_array_id, $term5_array_id )
      );

最后,我可以单独调用每个术语列表:

<ul>
    <?php wp_list_categories( $args ); ?>
    <?php wp_list_categories( $args_1 ); ?>
    <?php wp_list_categories( $args_2 ); ?>
</ul>

答案 6 :(得分:0)

我没有找到任何东西,所以我构建了自己的方法。我在我的插件的抽象类中将它抽象出来,因此有额外的代码,但您可以提取方法。

主要看的方法是format_hierarchy()

// The parent class
abstract class Taxonomy {
    protected bool $_terms_loaded;
    
    protected array $terms;
    protected array $formatted_terms;
    
    public function __get( $property ) {
        if ( $property === 'formatted_terms' ) {
            if ( !isset( $this->formatted_terms ) ) $this->format_hierarchy();
            return $this->formatted_terms;
        }
        
        if ( substr( $property, 0, 1 ) === '_' ) die( 'Cannot get private properties' );

        if ( property_exists( $this, $property ) )
            return $this->$property;
    }

    /**
     * Formats the taxonomy's terms into a hierarchy of term_blocks and saves the value as a property to the class
     * 
     * @return              array       an array of `[term_taxonomy_id:number] => term_block` like:
     *                                      array(
     *                                          array( // parent $term_block
     *                                              'term' => WP_Term,
     *                                              'children' => array( $term_blocks… )
     *                                          ),
     *                                          …$term_blocks…
     *                                      )
     */
    public function format_hierarchy():array {
        if ( !$this->_load_terms() ) return [];

        // Holds a reference to every category, parents and children
        $term_blocks = [];

        // Holds a reference to every top most level category
        $parents = [];

        foreach ( $this->terms as $term ) {
            // Add itself to the list of all categories
            $term_block = [
                'children' => [],
                'term' => $term
            ];
            
            // Add itself to the array of all categories
            if ( !isset( $term_blocks[ $term->term_taxonomy_id ] ) )
                $term_blocks[ $term->term_taxonomy_id ] =& $term_block;
            
            // If it's a child category…
            if ( $term->parent !== 0 ) {
                // If the parent hasn't been created yet, create it
                if ( !isset( $term_blocks[ $term->parent ] ) )
                    $term_blocks[ $term->parent ] = [
                        'children' => [],
                        'term' => null
                    ];
                    
                $term_blocks[ $term->parent ][ 'children' ][] =& $term_block;
            } else
                // Otherwise it's a parent
                $parents[ $term->term_taxonomy_id ] =& $term_blocks[ $term->term_taxonomy_id ];

            // set the term block's WP_Term property
            $term_blocks[ $term->term_taxonomy_id ][ 'term' ] =& $term;
            // This is needed so that the loop doesn't readd the same reference over and over again
            unset( $term ); unset( $term_block );
        }
        
        return $this->formatted_terms = $parents;
    }

    /**
     * Given a WP_Term property value, and a property key, recursively searches through all of the terms for it
     * 
     * @property    $term_val       mixed       The property value to find
     * @property    $prop           string      The property key for the value
     * @property    $with_parent    ?boolean    Whether to return the top level parent as well
     * @property    $term_blocks    ?array      Array of term blocks
     * @return                      array       If $with_parent is true, returns an [ $found_term_block, $top_level_parent ]
     *                                          Otherwise returns only the found term block
     */
    public function find_term_by(
        $term_val,
        string $prop,
        bool $with_parent = false,
        $term_blocks = null
    ):?array {
        if ( is_null( $term_blocks ) ) $term_blocks = $this->formatted_terms;
        foreach ( $term_blocks as $term_block ) {
            if ( $term_block[ 'term' ]->{$prop} === $term_val ) return $term_block;
            if ( count( $term_block[ 'children' ] ) &&
                ( $found = $this->find_term_by( $term_val, $prop, false, $term_block[ 'children' ] ) )
            ) return $with_parent ? [ $found, $term_block ] : $found;
        }
        return null;
    }

    /**
     * Loads the taxonomy terms once from the DB
     */
    protected function _load_terms():bool {
        if ( isset( $this->_terms_loaded ) ) return $this->_terms_loaded;
        
        $this->terms = get_terms(
            array(static::$taxonomy),
            array(
                    'hide_empty'    => false,
                )
        );

        if ( !$this->terms ) {
            ClassErrorHandler::handle_exception(
                new \WP_Error( 500, 'Failed to load category terms: \'' . static::$taxonomy . '\'' )
            );
        }

        return $this->_terms_loaded = !!$this->terms;
    }
}

// The Implementation
class TaxonomyProductService extends Taxonomy {
    public static string $taxonomy;
    public static string $slug;

    /**
     * To be called upon taxonomy registration long before any instance is required
     */
    public static function define_taxonomy( string $slug, string $taxonomy ) {
        static::$slug = $slug;
        static::$taxonomy = $taxonomy;
    }
}

在注册我调用的自定义分类法之后 TaxonomyProductService::define_taxonomy('url-slug', 'product-service');

最后是如何使用

$tax = new TaxonomyProductService();
$terms = $tax->formatted_terms;
// search for a term whose slug === `my-term`, and return the parent category
list( $current_term, $parent_term ) = $tax->find_term_by( 'my-term', 'slug', true );

答案 7 :(得分:-1)

使用类别顺序和分类术语订购免费插件