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

Custom Field Alphabetical Index WordPress

  • SOLVED

Hello -

I am trying to create a page that sorts a list of custom fields alphabetically nested under the correct letter that the custom field begins with.

I have build this page and have it working when just using a page title of a certain post type. You can see what that looks like here: http://numbertwoguide.com/dictionary/glossary/

Again, this is simply using the page title a post type.

I want to do the same thing for another post type. The only difference is that each page for this new post type has a custom field value associated with it. I want to organize this new page so it sorts by the custom field value alphabetically and not the post title.

Below is the code I was using for the page title. The name of the custom field I am using is 'faq_name'.

Please let me know if you have any questions.


<?php

for ($i=65; $i<=90; $i++){

$first_char = chr($i);

$postids=$wpdb->get_col($wpdb->prepare("
SELECT ID
FROM $wpdb->posts
WHERE SUBSTR($wpdb->posts.post_title,1,1) = %s
ORDER BY $wpdb->posts.post_title",$first_char));

if ($postids) {
$args=array(
'post__in' => $postids,
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'caller_get_posts'=> 1,
'post_type'=> 'dictionary'
);

$my_query = null;
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {
echo '<div class="gloss-letter">' . $first_char . '</div>';
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<p class="gloss-term"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p>
<?php
endwhile;
}
}

wp_reset_query(); // Restore global post data stomped by the_post().
}
?>


Answers (2)

2016-08-09

Andrea P answers:

it should work if you just add the ordering to the $args array


$args=array(
'post__in' => $postids,
'post_status' => 'publish',
'posts_per_page' => -1,
'post_type'=> 'dictionary',
'meta_key' => 'faq_name',
'orderby' => 'meta_value',
'order' => 'ASC'
);


jpequens comments:

I've tried that and get no results. The meta_key is not a number, but just a shortened title. I think that may be why it does not work...


Andrea P comments:

sorry I've edited the answer! I made a typo in the first version. ;)


jpequens comments:

I'm getting the correct list of results, but it is nesting them under the letter that the post title begins with. I would want them to be nested under the letter that the custom field begins with. Any thoughts?


Andrea P comments:

that code should order by the value of the custom field called "faq_name".
if it's sorting by the title could mean that the query cannot find the field "faq_name".

are you sure that the meta field key is "faq_name"?


jpequens comments:

Yes, and it is sorting that alphabetically. The problem is that if the title of the post is "This is the post?" and the value of 'faq_name' is "My Value". It is putting "My Value" under the letter "T" on the page and not under the letter "M".


Andrea P comments:

ah ok wait, I just noticed that your code is built to retrieve the posts with the same first letter of the title (the first bit of code).
I thought that this was just about ordering something which was already correctly retrieved..

unfortunately the meta fields are not in the same database table of the general posts, and the sql query would have to be re-made from scratch.

sorry but it's late here and I am too tired to focus on an issue like this, especially for $5.

if nobody else have suggest a solution, I'll have a look tomorrow morning EU time.

cheers


jpequens comments:

Ah, appreciate it. Yeah, I think that is the issue.


jpequens comments:

Not sure how to run that database table correctly...


Andrea P comments:

a possible solution would be if you create a specific custom field with the letter where the post have to be grouped.

by instance

'faq_letter' = 'F'
'faq_letter' = 'B'

then you can scrap all that sql thing, and make your $args in this way


$args=array(
'post_type'=> 'dictionary',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_key' => 'faq_letter',
'meta_value' => $first_char,
'meta_compare' => '='
);


in this way the args will tell to retrieve only the posts which have faq_letter equal to the currently looped letter

2016-08-10

Rempty answers:

Hello jpequens
You can use this to replace your query

for ($i=65; $i<=90; $i++) {
$first_char = chr($i);
$query = "SELECT " . $wpdb->prefix . "posts.ID FROM " . $wpdb->prefix . "posts INNER JOIN " . $wpdb->prefix . "postmeta ON ( " . $wpdb->prefix . "posts.ID = " . $wpdb->prefix . "postmeta.post_id ) WHERE 1=1 AND ( ( " . $wpdb->prefix . "postmeta.meta_key = 'faq_name' AND CAST(" . $wpdb->prefix . "postmeta.meta_value AS CHAR) LIKE '" . $first_char . "%' ) ) AND " . $wpdb->prefix . "posts.post_type = 'dictionary' AND ((" . $wpdb->prefix . "posts.post_status = 'publish')) GROUP BY " . $wpdb->prefix . "posts.ID ORDER BY " . $wpdb->prefix . "postmeta.meta_value ASC";
$postids = $wpdb->get_col($query);
if ($postids) {
echo '<div class="gloss-letter">' . $first_char . '</div>';
foreach ($postids as $id) {
$post = get_post(intval($id));
setup_postdata($post);
?>
<p class="gloss-term"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p>
<?php
}
}
}


PD: will be nice if you can rise the prize pool


jpequens comments:

That worked perfect! Thank you very much!