0

I have a loop definition like this in functions.php:

function artist_list($query) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    // Target the artists page
    if (is_tax('artist-category')) {
        $query->set('posts_per_page', '-1');
        $query->set('orderby', 'meta_value');
        $query->set('meta_key', 'artist_last_name');
        $query->set('order', 'ASC');
    }
}
add_action('pre_get_posts', 'artist_list');

I'm listing artists from taxonomy and alphabetising them according their last name. But on some occasions the artists should be alphabetised by the first name, and this should be controlled inside each post from the back end.

I need info from the post before the loop starts, and I can only get it in the loop.

I'm gonna make a checkbox in the backend where the user can choose how to alphabetise. Roughly like this:

enter image description here

How should I do this? Is the pre_get_posts the answer?

1

Don't try to make WP_Query, or SQL, do this. In the backend, don't save artist_last_name save something like artist_sort_name instead, and set it to either first or last name accordingly, then sort on that normalized key.

To sort conditionally with WP_Query-- that is, to ignore my advise above and try to make WP_Query/SQL do this-- you would need to write a filter and some relatively complicated SQL that would not likely be very efficient-- that is, it would likely execute slowly.

See the following for a similar question/answer:

https://wordpress.stackexchange.com/a/134001/21376

| improve this answer | |
1

For future generations, here's what I ended up doing.

Use artist_sort_name for sorting and just change the value in that field to artist_first_name or artist_last_name (thanks to s_ha_dums answer).

I'm using WPAlchemy class to make the metaboxes and custom fields. I had to call the save_filter to run a function before the save (this is in functions.php file):

// Save filter function, check the value of alphabetize custom field
// if it's set then use first name as sort name
function nd_meta_sort($meta, $post_id) {
    if ($meta['alphabetize'] == "alphabetize") {
        $meta['artist_sort_name'] = $meta['artist_first_name'];
    } else {
        $meta['artist_sort_name'] = $meta['artist_last_name'];
    }
    return $meta;
}

And here's how the metabox is defined in functions.php:

// Metabox for artists
$custom_metabox_artist = new WPAlchemy_MetaBox(array(
    'id'                 => 'artist_custom_meta',
    'title'              => 'Artist Info',
    'template'           => TEMPLATEPATH . '/assets/meta-artists.php',
    'types'              => array('artists'),
    'mode'               => WPALCHEMY_MODE_EXTRACT,
    'hide_screen_option' => TRUE,
    'save_filter'        => 'nd_meta_sort' // This get executed when saving the post
));

And here's the actual metabox:

<table>
    <tbody>
        <tr>
            <th>
                <label>First Name:</label>
            </th>
            <td>
                <!-- Field for the first name -->
                <?php $mb->the_field('artist_first_name'); ?>
                <input name="<?php $mb->the_name(); ?>" class="artist-name" type="text" value="<?php $mb->the_value(); ?>">
                <!-- Checkbox for for choosing which field to sort -->
                <span>
                    <?php $mb->the_field('alphabetize'); ?>
                    <input type="checkbox" name="<?php $mb->the_name(); ?>" value="alphabetize" <?php $mb->the_checkbox_state('alphabetize'); ?>>
                    Alphabetize First Name
                </span>
            </td>
        </tr>
        <tr>
            <th>
                <label>Lastname:</label>
            </th>
            <td>
                <!-- Field for the last name -->
                <?php $mb->the_field('artist_last_name'); ?>
                <input name="<?php $mb->the_name(); ?>" class="artist-name" type="text" value="<?php $mb->the_value(); ?>">
            </td>
        </tr>
    </tbody>
</table>
<!-- The field the post are sorted to. Note that it's hidden -->
<?php $mb->the_field('artist_sort_name'); ?>
<input name="<?php $mb->the_name(); ?>" class="artist-name sort-name" type="hidden" value="<?php $mb->the_value(); ?>">

The table is no means mandatory there, it's just how label/field pares are usually displayed in WP backend.

It looks something like this:

enter image description here

And sake of completeness here's the loop that gets the artists. I'm using the pre_get_posts in functions.php:

function artist_list($query) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    // Target the artists page
    if (is_tax('artist-category')) {
        $query->set('posts_per_page', '-1');
        $query->set('orderby', 'meta_value');
        $query->set('meta_key', "artist_sort_name");
        $query->set('order', 'ASC');
    }
}
add_action('pre_get_posts', 'artist_list');
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.