,我与之没有任何关联)在本地测试安装上进行调试。此插件捕获所有错误并将其显示在屏幕上。我已经对代码进行了注释,因此很容易理解我的操作。在我留下的几个地方,我不太确定实际值应该是多少。一定要看看那些
我添加了一个名为term_order
. 如果此属性为空,all 术语按字母顺序显示。您还可以通过以下方式指定特定订单term name (我在这里使用术语名称,因为您的客户端似乎会传递术语名称,而不是slug或id。如果您要传递id或slug,只需相应地修改代码即可)。此属性按照您希望显示的顺序接受一个逗号分隔的术语名称字符串。例如:
term_order="cityguides, travelguides, languageguides"
这将只显示这三个任期的帖子,按cityguides
, travelguides
, languageguides
. 术语名称将仅显示在该特定术语的第一篇文章之前中有错误usort()
多年来,它仍然是不固定的。这就是bug
usort():用户比较函数修改了数组
到目前为止,就像我说的,这个bug还没有修复。最好的解决方案是通过使用@
在之前签名usort()
. 请注意,您应该never 使用此方法抑制错误和bug,以及所有错误和bugmust 是固定的。因为这是一个php核心错误,似乎永远不会被修复,所以建议在修复错误之前使用此方法。查看错误详细信息here
只有当一篇文章属于一个术语时,这个短代码才可靠。如果一篇文章附加了多个术语,则显示在文章顶部的术语名称可能会产生意外的效果。对于多期帖子,最好使用单独的短代码或扩展我的代码来处理
我内置了一个系统,在将术语名称传递给term_order
属性因此,您无需担心空格和因此而导致的短代码失败
重要提示,一篇文章应该至少附有一个术语。没有条款的帖子会导致bug和短代码失败。由于本周出现的个人问题造成的时间限制,我没有对此采取任何预防措施。当一篇文章没有任何条款时,您可以扩展短码以适应这种情况
根据需要修改和使用代码
由于使用了短数组语法,此代码需要PHP 5.4以上版本([]
) 支持旧语法(array()
). 我还使用了数组解引用(get_the_terms( $post->ID, $taxonomy )[0]->name
)也仅在PHP 5.4中可用+
这是代码
// create shortcode with parameters so that the user can define what\'s queried - default is to list all blog posts
add_shortcode( \'books\', \'books_shortcode\' );
function books_shortcode( $atts ) {
ob_start();
// Do not use extract(), use this syntax for your attributes
$attributes = shortcode_atts(
[
\'term_order\' => \'\', // New attribute to sort your terms in a custom order, pass a comma deliminated spaced string here. Default is term name
\'taxonomy\' => \'booktypes\',
\'type\' => \'books\',
\'order\' => \'ASC\',
\'orderby\' => \'post_title\',
\'posts\' => -1,
],
$atts
);
$taxonomy = filter_var( $attributes[\'taxonomy\'], FILTER_SANITIZE_STRING );
// Check if our taxonomy is valid to avoid errors and bugs. If invalid, return false
if ( !taxonomy_exists( $taxonomy ) )
return false;
//Set the variables for sorting purposes
$orderby = filter_var( $attributes[\'orderby\'], FILTER_SANITIZE_STRING );
$order = filter_var( $attributes[\'order\'], FILTER_SANITIZE_STRING );
// Convert the string of term names to an array
$tax_query = [];
if ( $attributes[\'term_order\'] ) {
// First we need to remove the whitespaces before and after the commas
$no_whitespaces = preg_replace( \'/\\s*,\\s*/\', \',\', filter_var( $attributes[\'term_order\'], FILTER_SANITIZE_STRING ) );
$terms_array = explode( \',\', $no_whitespaces );
/*
* As we are using term names, and due to a bug in tax_query, we cannot pass term names to a tax_query
* We are going to use get_term_by to get the term ids
*/
foreach ( $terms_array as $term ) {
$term_ids_array[] = get_term_by( \'name\', $term, $taxonomy )->term_id;
}
// Build a tax_query to get posts from the passed term names in $attributes[\'term_order\']
$tax_query = [
[
\'taxonomy\' => $taxonomy,
\'terms\' => $term_ids_array,
\'include_children\' => false
],
];
}
// Pass your attributes as query arguments, remember to filter and sanitize user input
$options = [
\'post_type\' => filter_var( $attributes[\'type\'], FILTER_SANITIZE_STRING ),
\'posts_per_page\' => filter_var( $attributes[\'posts\'], FILTER_VALIDATE_INT ),
\'tax_query\' => $tax_query
];
$query = new WP_Query( $options );
/**
* We need to sort the loop now before we run it. If the custom attribute, term_order is an empty array or not a valid array,
* we will sort by term name, ascending. If a valid array of term names is passed, we will sort by the order given
*
* There is a bug in usort causing the following error:
* usort(): Array was modified by the user comparison function
* @see https://bugs.php.net/bug.php?id=50688
* This bug has yet to be fixed, when, no one knows. The only workaround is to suppress the error reporting
* by using the @ sign before usort
*/
@usort( $query->posts, function ( $a, $b ) use ( $taxonomy, $terms_array, $order, $orderby )
{
// We will use names, so the array should be names as well. Change according to needs
$array_a = get_the_terms( $a->ID, $taxonomy )[0]->name;
$array_b = get_the_terms( $b->ID, $taxonomy )[0]->name;
// If the post terms are the same, orderby the value of $attributes[\'orderby\']
if ( $array_a != $array_b ) {
// If $terms_array is empty, sort by name default
if ( !$terms_array )
return strcasecmp( $array_a, $array_b );
$array_flip = array_flip( $terms_array );
return $array_flip[$array_a] - $array_flip[$array_b];
} else {
$orderby_param = [\'ID\', \'post_date\', \'post_date_gmt\', \'post_parent\', \'post_modified\', \'post_modified_gmt\', \'comment_count\', \'menu_order\'];
if ( in_array( $orderby, $orderby_param ) ) {
if ( $order == \'ASC\' ) {
return $a->$orderby - $b->$orderby;
} else {
return $b->$orderby - $a->$orderby;
}
} else {
if ( $order == \'ASC\' ) {
return strcasecmp( $a->$orderby, $b->$orderby );
} else {
return strcasecmp( $b->$orderby, $a->$orderby );
}
}
}
});
if ( $query->have_posts() ) {
//Will hold the term name of the previous post for comparison
$term_name_string = \'\';
// Start a counter in order to set our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs correctly
$counter = 0;
while ( $query->have_posts() ) {
$query->the_post();
// Display the term name
global $post;
$terms_array = get_the_terms( $post->ID, $taxonomy );
$term_name = $terms_array[0]->name;
/**
* If this $term_name_string is not $term_name, we have a lot to do like display term name,
* and opening and closing divs
*/
if ( $term_name_string != $term_name ) {
// Reset our counter back to 0 to set our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs correctly
$counter = 0;
/**
* We need to close our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs
* We also need to close our previous term div if term name changes
* Open our div to wrap each term in a block. We will do this in same way as our term names
* Also open our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs
*/
if ( $query->current_post != 0 ) {
echo \'</div></div> <!--/.wrap-->\'."\\n";
echo \'</div><!-- Close div on last post in term -->\';
}
// Use the term slug here
echo \'<div class="books-container \' . $terms_array[0]->slug . \'">\';
?>
<h2 id="<?php echo $taxonomy /*I don\'t know what this should be, so just correct my change */ ?>" style="margin:0px 0px 20px 0px; ">
<?php
echo $term_name;
?>
</h2>
<?php
echo "\\n".\'<div class="section_inner clearfix"><div class="section_inner_margin clearfix">\'."\\n";
} // end $term_name_string != $term_name if condition
/**
* Close our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs
* Open our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs on every third post
*/
if( $counter != 0 && $counter%3 == 0 ) {
echo \'</div></div> <!--/.wrap-->\'."\\n";
echo "\\n".\'<div class="section_inner clearfix"><div class="section_inner_margin clearfix">\'."\\n";
}
// Set the current term name to $term_name_string for comparison
$term_name_string = $term_name;
?>
<div <?php post_class(\'vc_span4 wpb_column column_container\'); ?> style="padding-bottom: 60px;">
<div class="wpb_wrapper">
<?php // Get the post thumbnail ?>
<?php if ( has_post_thumbnail() ) { ?>
<div class="wpb_single_image wpb_content_element element_from_fade element_from_fade_on">
<div class="wpb_wrapper">
<?php
//$large_image_url = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), \'Book-thumbnail\' );
echo \'<a href="\' . get_permalink() . \'" title="\' . the_title_attribute( \'echo=0\' ) . \'" class="book-holder" ><span class="book-thumb">\';
echo get_the_post_thumbnail( $post->ID, \'book-thumbnail\' );
echo \'</span></a>\';
?>
</div>
</div>
<?php } ?>
</div>
<div class="wpb_text_column wpb_content_element text-align-center" style="margin: 20px 0px 0px 0px; ">
<div class="wpb_wrapper">
<h5><?php the_title(); ?></h5>
</div>
<a href="<?php the_permalink(); ?>" target="_blank" class="qbutton small" style="margin: 20px 0px 0px 0px; "><?php _e(\'More Info\', \'qode\'); ?></a>
</div>
</div>
<?php
if ( ( $query->current_post + 1 ) == $query->post_count ) {
echo \'</div></div> <!--/.wrap-->\'."\\n";
echo \'</div><!-- Close div on last post -->\';
}
$counter++;
}
wp_reset_postdata();
return ob_get_clean();
}
}
如果要使用术语段塞而不是术语名称,这里是我的代码的修改版本// create shortcode with parameters so that the user can define what\'s queried - default is to list all blog posts
add_shortcode( \'books\', \'books_shortcode\' );
function books_shortcode( $atts ) {
ob_start();
// Do not use extract(), use this syntax for your attributes
$attributes = shortcode_atts(
[
\'term_order\' => \'\', // New attribute to sort your terms in a custom order, pass a comma deliminated spaced string here. Default is term slug
\'taxonomy\' => \'booktypes\',
\'type\' => \'books\',
\'order\' => \'ASC\',
\'orderby\' => \'title\',
\'posts\' => -1,
],
$atts
);
$taxonomy = filter_var( $attributes[\'taxonomy\'], FILTER_SANITIZE_STRING );
// Check if our taxonomy is valid to avoid errors and bugs. If invalid, return false
if ( !taxonomy_exists( $taxonomy ) )
return false;
//Set the variables for sorting purposes
$orderby = filter_var( $attributes[\'orderby\'], FILTER_SANITIZE_STRING );
$order = filter_var( $attributes[\'order\'], FILTER_SANITIZE_STRING );
// Convert the string of term slugs to an array
$tax_query = [];
if ( $attributes[\'term_order\'] ) {
// First we need to remove the whitespaces before and after the commas
$no_whitespaces = preg_replace( \'/\\s*,\\s*/\', \',\', filter_var( $attributes[\'term_order\'], FILTER_SANITIZE_STRING ) );
$terms_array = explode( \',\', $no_whitespaces );
// Build a tax_query to get posts from the passed term slugs in $attributes[\'term_order\']
$tax_query = [
[
\'taxonomy\' => $taxonomy,
\'field\' => \'slug\',
\'terms\' => $terms_array,
\'include_children\' => false
],
];
}
// Pass your attributes as query arguments, remember to filter and sanitize user input
$options = [
\'post_type\' => filter_var( $attributes[\'type\'], FILTER_SANITIZE_STRING ),
\'posts_per_page\' => filter_var( $attributes[\'posts\'], FILTER_VALIDATE_INT ),
\'tax_query\' => $tax_query
];
$query = new WP_Query( $options );
/**
* We need to sort the loop now before we run it. If the custom attribute, term_order is an empty array or not a valid array,
* we will sort by term name, ascending. If a valid array of term names is passed, we will sort by the order given
*
* There is a bug in usort causing the following error:
* usort(): Array was modified by the user comparison function
* @see https://bugs.php.net/bug.php?id=50688
* This bug has yet to be fixed, when, no one knows. The only workaround is to suppress the error reporting
* by using the @ sign before usort
*/
@usort( $query->posts, function ( $a, $b ) use ( $taxonomy, $terms_array, $order, $orderby )
{
// We will use names, so the array should be names as well. Change according to needs
$array_a = get_the_terms( $a->ID, $taxonomy )[0]->name;
$array_b = get_the_terms( $b->ID, $taxonomy )[0]->name;
// If the post terms are the same, orderby the value of $attributes[\'orderby\']
if ( $array_a != $array_b ) {
// If $terms_array is empty, sort by name default
if ( !$terms_array )
return strcasecmp( $array_a, $array_b );
$array_flip = array_flip( $terms_array );
return $array_flip[$array_a] - $array_flip[$array_b];
} else {
$orderby_param = [\'ID\', \'post_date\', \'post_date_gmt\', \'post_parent\', \'post_modified\', \'post_modified_gmt\', \'comment_count\', \'menu_order\'];
if ( in_array( $orderby, $orderby_param ) ) {
if ( $order == \'ASC\' ) {
return $a->$orderby - $b->$orderby;
} else {
return $b->$orderby - $a->$orderby;
}
} else {
if ( $order == \'ASC\' ) {
return strcasecmp( $a->$orderby, $b->$orderby );
} else {
return strcasecmp( $b->$orderby, $a->$orderby );
}
}
}
});
if ( $query->have_posts() ) {
//Will hold the term name of the previous post for comparison
$term_name_string = \'\';
// Start a counter in order to set our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs correctly
$counter = 0;
while ( $query->have_posts() ) {
$query->the_post();
// Display the term name
global $post;
$terms_array = get_the_terms( $post->ID, $taxonomy );
$term_name = $terms_array[0]->name;
/**
* If this $term_name_string is not $term_name, we have a lot to do like display term name,
* and opening and closing divs
*/
if ( $term_name_string != $term_name ) {
// Reset our counter back to 0 to set our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs correctly
$counter = 0;
/**
* We need to close our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs
* We also need to close our previous term div if term name changes
* Open our div to wrap each term in a block. We will do this in same way as our term names
* Also open our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs
*/
if ( $query->current_post != 0 ) {
echo \'</div></div> <!--/.wrap-->\'."\\n";
echo \'</div><!-- Close div on last post in term -->\';
}
// Use the term slug here
echo \'<div class="books-container \' . $terms_array[0]->slug . \'">\';
?>
<h2 id="<?php echo $taxonomy /*I don\'t know what this should be, so just correct my change */ ?>" style="margin:0px 0px 20px 0px; ">
<?php
echo $term_name;
?>
</h2>
<?php
echo "\\n".\'<div class="section_inner clearfix"><div class="section_inner_margin clearfix">\'."\\n";
} // end $term_name_string != $term_name if condition
/**
* Close our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs
* Open our \'section_inner clearfix\' and \'section_inner_margin clearfix\' divs on every third post
*/
if( $counter != 0 && $counter%3 == 0 ) {
echo \'</div></div> <!--/.wrap-->\'."\\n";
echo "\\n".\'<div class="section_inner clearfix"><div class="section_inner_margin clearfix">\'."\\n";
}
// Set the current term name to $term_name_string for comparison
$term_name_string = $term_name;
?>
<div <?php post_class(\'vc_span4 wpb_column column_container\'); ?> style="padding-bottom: 60px;">
<div class="wpb_wrapper">
<?php // Get the post thumbnail ?>
<?php if ( has_post_thumbnail() ) { ?>
<div class="wpb_single_image wpb_content_element element_from_fade element_from_fade_on">
<div class="wpb_wrapper">
<?php
//$large_image_url = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), \'Book-thumbnail\' );
echo \'<a href="\' . get_permalink() . \'" title="\' . the_title_attribute( \'echo=0\' ) . \'" class="book-holder" ><span class="book-thumb">\';
echo get_the_post_thumbnail( $post->ID, \'book-thumbnail\' );
echo \'</span></a>\';
?>
</div>
</div>
<?php } ?>
</div>
<div class="wpb_text_column wpb_content_element text-align-center" style="margin: 20px 0px 0px 0px; ">
<div class="wpb_wrapper">
<h5><?php the_title(); ?></h5>
</div>
<a href="<?php the_permalink(); ?>" target="_blank" class="qbutton small" style="margin: 20px 0px 0px 0px; "><?php _e(\'More Info\', \'qode\'); ?></a>
</div>
</div>
<?php
if ( ( $query->current_post + 1 ) == $query->post_count ) {
echo \'</div></div> <!--/.wrap-->\'."\\n";
echo \'</div><!-- Close div on last post -->\';
}
$counter++;
}
wp_reset_postdata();
return ob_get_clean();
}
}
用法现在您可以使用以下短代码:(我使用了默认的帖子类型post
和分类学category
出于测试目的,这就解释了我对属性的使用[books type=\'post\' taxonomy=\'category\' term_order="cityguides, travelguides, languageguides"]
将显示术语中的帖子cityguides
, travelguides
, languageguides
按照特定的顺序根据评论编辑,同一期限内的帖子排序顺序存在问题,因为我们只按期限排序。要获得正确的排序顺序,最好的方法是
从查询中删除排序顺序,因为它实际上并不重要
调整中的代码usort
作用我们需要按术语和orderby
属性为了做到这一点,我们需要比较两个帖子中的术语,如果它们相同,则按orderby
我已经更新了上述两个代码示例中的代码,以反映这些更改。这里的一个重大变化是您传递给的值orderby
因为我们现在将按post属性订购。您需要检查有效的WP_Post
properties 并使用它们来代替default values used with WP_Query
因此,例如,如果需要按标题对帖子进行排序,那么该值将为post_title
而不是title
. 如果要按发布日期排序,则值为post_date
而不是date
与正常情况一样WP_query
我希望这是有意义的。