简体   繁体   中英

How to sort a Wordpress post query by an optional custom field or the post title?

I want to sort the result of a WP_query() alphabetically by nickname (optional custom field) if present, last name (in post title) if not.

Sorting order:

  1. If they have a nickname, use that to sort by.
  2. If they do not, use their last name to sort by.

Sample data:

Post 1
    Title: 'John Adams'
    Nickname: ''

Post 2
    Title: 'Joe Car'
    Nickname: ''

Post 3
    Title: 'John Earnest'
    Nickname: ''

Post 4
    Title: 'James Water'
    Nickname: 'Bumblebee'

Post 5
    Title: 'John Zebra'
    Nickname: 'Disco'

Desired output:

An object/array similar in structure to a result of WP_query() (that I can check have_posts against); that has posts in this order

  1. John A dams
  2. John ' B umblebee' Water
  3. Joe C ar
  4. James ' D isco' Zebra
  5. John E arnest

The post_title is a person's first and last name.

There is an optional custom field for the person's nickname, custom_field_nickname .

I want to return all the superhero -type posts (that either have a nickname or do not). Current query:

$args = array( 'post_type' => 'superhero' );
$query = new WP_Query( $args );

Currently my function that sort these posts using add_filter :

function posts_orderby_lastname ($orderby_statement)
{
  $orderby_statement = "RIGHT(post_title, LOCATE(' ', REVERSE(post_title)) - 1) ASC";
    return $orderby_statement;
}

How can I modify that filter or somehow set the orderby option for my desired post order?

Use below code to address your requirement:

<?php
query_posts(array('post_type' => 'superhero'));
$names = array();
?>

<?php if ( have_posts() ) : ?>
<?php while (have_posts()) : the_post(); ?>
    <div id="lists">
    <ul>
    <?php
    // check whether custom field exist or not
    if (get_post_meta($post->ID, 'nick_name', true) ) { // custom field exist
        $explode = explode(' ',get_the_title()); // explode main title
        $nick = get_post_meta($post->ID, 'nick_name', true); // get nickname
        $names[] = $explode[0].' '.$nick.' '.$explode[1]; // form a name with Firstname Nickname LastName
    } else { // no custom field value
        $explode = explode(' ',get_the_title());  // explode main title
        $names[] = $explode[0].' '.$explode[1]; // Form a name with Firstname Lastname
    }
    ?>
    </ul>
    </div>
<?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_query();?>

<?php
    /* Sort function to sort array */
    function cmp($a, $b)
    {
        $a = substr(strstr($a," "), 1);
        $b = substr(strstr($b," "), 1);
        return strcasecmp($a, $b);
    }

    uasort($names, "cmp");
    foreach ($names as $key => $value) {
        echo $value.'<br />';
    }
?>

So I ended up doing this:

// Build post queries
$query = new WP_Query($args);
// Extract post array from objects
$queryPosts = $query->posts;
// Custom sort each array according to "nickname"
usort($queryPosts, compare_the_posts);
// Replace old array of posts with newly sorted one
$query->posts = $queryPosts;

Combined with this custom compare function

// If a post has a specified "nickname", use that to sort with. If not, use the last word of the post title (last name)
function compare_posts($a, $b) {
    if (strlen($a->nick_name) > 0) {
        $a = $a->nick_name;
    } else {
        $a = last_word($a->post_title);
    }
    if (strlen($b->nick_name) > 0) {
        $b = $b->nick_name;
    } else {
        $b = last_word($b->post_title);
    }
  return strcasecmp($a, $b);
}

// (Helper function) Last word of a sentence
function last_word($str) {
    $last_word_pos = strrpos($str, ' ') + 1;
    $last_word = substr($str, $last_word_pos);
    return $last_word;
}

Hope this will help you.

REQUEST:SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta
   ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1
   ON (wp_posts.ID = mt1.post_id)
WHERE 1=1
   AND wp_posts.post_type = 'post'
   AND (wp_posts.post_status = 'publish')
   AND (wp_postmeta.meta_key = 'about_order'
   AND mt1.meta_key = 'job_title' )
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value DESC
LIMIT 0, 12

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM