Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Orderby custom field, alphabetically WordPress

  • SOLVED

Please can someone help me write a custom loop that orders first by the contents of a custom field and second, alphabetically by post title.

I have a custom field associated with each post entitled 'Promote'.

When 'Promote' has a value of 'Yes', I would like those posts to appear first in the loop. Regular posts would follow promoted posts with both regular and promoted posted ordered alphabetically by post title.

All non-promoted posts will have a 'Promote' custom field value of 'No'.

The custom loop should retain standard WordPress pagination enabling manipulation via the 'Reading > Blog pages show at most X posts' feature in the WordPress admin.

Many thanks.

<strong>CLARIFICATION</strong>: the loop should be universal and work equally as a category loop, tag loop, search loop and index loop. Thanks.

Answers (4)

2010-11-25

Pau answers:

Here's my simple method for post_title to alphabetically ordered and your custom field value ordered and still retain the pagination function.

function custom_orderby($orderby){
return "meta_value DESC, post_title DESC";
}
add_filter('posts_orderby', 'custom_orderby');
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'paged' => $paged,
'meta_key' => 'promote'
);
query_posts($args);


insert it at the top of:

if ( have_posts() ) while ( have_posts() ) : the_post();

<strong>NOTE:</strong> this work anywhere that have loop

2010-11-25

MagoryNET answers:

You have to make a custom query:


<?php

global $wpdb;
$querystr = "
SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wpostmeta.meta_key = 'Promote'
AND wposts.post_status = 'publish'
AND wposts.post_type = 'post'
ORDER BY wpostmeta.meta_value DESC, wposts.post_date DESC
";

$pageposts = $wpdb->get_results($querystr, OBJECT);

// start of the loop

<?php if ($pageposts): ?>
<?php global $post; ?>
<?php foreach ($pageposts as $post): ?>
<?php setup_postdata($post); ?>

// here is the loop

// end of the loop

<?php endforeach; ?>
<?php else : ?>
<h2 class="center">Not Found</h2>
<p class="center">Sorry, but you are looking for something that isn't here.</p>
<?php include (TEMPLATEPATH . "/searchform.php"); ?>
<?php endif; ?>


$pageposts = $wpdb->get_results($querystr, OBJECT);

?>



You should probably add an index on meta_key, meta_value pair and add some LIMIT (using $paged) to the query (probably $paged*15, 15 or sth - depending on your page size).

2010-11-25

Jimish Gamit answers:


<?php
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE $wpdb->postmeta.meta_key = 'Promote'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
ORDER BY $wpdb->postmeta.meta_value DESC,$wpdb->posts.post_date DESC ";

$pageposts = $wpdb->get_results($querystr, OBJECT); ?>


<?php if ($pageposts): ?>

<?php global $post; ?>

<?php foreach ($pageposts as $post): ?>

<?php setup_postdata($post); ?>



// here is the loop



// end of the loop



<?php endforeach; ?>

<?php else : ?>

<h2 class="center">Not Found</h2>

<p class="center">Sorry, but you are looking for something that isn't here.</p>

<?php include (TEMPLATEPATH . "/searchform.php"); ?>

<?php endif; ?>

$pageposts = $wpdb->get_results($querystr, OBJECT);

?>

2010-11-25

Rok Don answers:

$querystr = "
SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wpostmeta.meta_key = 'Promote'
AND wposts.post_type = 'post'
ORDER BY wpostmeta.meta_value DESC
";


designbuildtest comments:

MagoryNET, Jimish Gamit & Rok Don, thank you, these all look very promising. Please could someone piece all the code together and include my loop (below)

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h2 class="entry-title"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
<?php the_content(); ?>
</div>


Rok Don comments:

<?php
$querystr = "
SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wpostmeta.meta_key = 'Promote'
AND wposts.post_type = 'post'
ORDER BY wpostmeta.meta_value DESC
";
$pageposts = $wpdb->get_results($querystr, OBJECT);
if ($pageposts):
global $post;
foreach ($pageposts as $post):
setup_postdata($post); ?>

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

<h2 class="entry-title"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>

<?php the_content(); ?>

</div>
<?php endforeach;

else : ?>

<h2 class="center">Not Found</h2>

<p class="center">Sorry, but you are looking for something that isn't here.</p>

<?php endif; ?>