admin管理员组

文章数量:1287514

In this project, there are custom posts with a variety of titles. In each post with the title that is the name of a person (first name, last name), there is a custom field (custom_title) that can hold an alternate name (last name, first name).

In order to display the names in a useful way in the custom archive page, the object is to check for a value in the custom_title field and if present update the post title with the custom title. After all of the applicable titles have been updated, the query must sort all of the posts by title, all the while recognizing the updated titles.

Using the code below, the original titles of the name articles are updated with the custom titles, but the sort order doesn't change--it still sorts by the original title.

Thanks for taking the time to help!

    function cchs_swap_title( $updatedTitle) 
    {
        $customTitle = get_post_meta( get_the_ID(), 'custom_title', true);
        if(!empty($customTitle))
        {
            $updatedTitle = $customTitle;
        }
        return $updatedTitle;
    }
    add_filter( 'the_title', 'cchs_swap_title');
    
    function cchs_archives_orderby( $the_query ) {
        if(!is_admin() && $the_query->is_main_query())
        {
            $the_query->set( 'orderby', 'title' );
            $the_query->set( 'order', 'DESC' );
            
        }
    }
    add_action( 'pre_get_posts', 'cchs_archives_orderby', 99999 );      

    $args = array(
        'post_type'         => 'cchs_article',
        'posts_per_page'    => -1
    );
    $the_query = new WP_Query( $args );

    if ( $the_query->have_posts() ) : 
        while ( $the_query->have_posts() ) : $the_query->the_post();
            get_template_part( 'template-parts/content', 'archive-cchs_article');
        endwhile;
        wp_reset_postdata();
    else :
        get_template_part( 'template-parts/content', 'none' );
    endif;

In this project, there are custom posts with a variety of titles. In each post with the title that is the name of a person (first name, last name), there is a custom field (custom_title) that can hold an alternate name (last name, first name).

In order to display the names in a useful way in the custom archive page, the object is to check for a value in the custom_title field and if present update the post title with the custom title. After all of the applicable titles have been updated, the query must sort all of the posts by title, all the while recognizing the updated titles.

Using the code below, the original titles of the name articles are updated with the custom titles, but the sort order doesn't change--it still sorts by the original title.

Thanks for taking the time to help!

    function cchs_swap_title( $updatedTitle) 
    {
        $customTitle = get_post_meta( get_the_ID(), 'custom_title', true);
        if(!empty($customTitle))
        {
            $updatedTitle = $customTitle;
        }
        return $updatedTitle;
    }
    add_filter( 'the_title', 'cchs_swap_title');
    
    function cchs_archives_orderby( $the_query ) {
        if(!is_admin() && $the_query->is_main_query())
        {
            $the_query->set( 'orderby', 'title' );
            $the_query->set( 'order', 'DESC' );
            
        }
    }
    add_action( 'pre_get_posts', 'cchs_archives_orderby', 99999 );      

    $args = array(
        'post_type'         => 'cchs_article',
        'posts_per_page'    => -1
    );
    $the_query = new WP_Query( $args );

    if ( $the_query->have_posts() ) : 
        while ( $the_query->have_posts() ) : $the_query->the_post();
            get_template_part( 'template-parts/content', 'archive-cchs_article');
        endwhile;
        wp_reset_postdata();
    else :
        get_template_part( 'template-parts/content', 'none' );
    endif;
Share Improve this question asked Oct 20, 2021 at 23:08 P. BrittenP. Britten 31 bronze badge
Add a comment  | 

2 Answers 2

Reset to default 0

If you are querying all posts at once with 'posts_per_page'=> -1 it would be easiest to get all posts as an array, update title if needed, and sort them after.

The disadvantage of that approach is you would have to update your loop to use properties instead of functions i.e. instead of the_title(); you would use echo $article->post_title; Example below would work without the cchs_swap_title filter and cchs_archives_orderby action.

$args = array(
        'post_type'         => 'cchs_article',
        'posts_per_page'    => -1
    );
$the_query = new WP_Query( $args );
$articles = $the_query->get_posts(); // Get all the posts as an array

// Update post title based on custom field
foreach ( $articles as $article ) {
    $customTitle = get_post_meta( $article->ID, 'custom_title', true);
    if( $customTitle ) {
        $article->post_title = $customTitle;
    }
}

// Sort all posts by title
usort($articles, function($a, $b) {
    return strcmp( $a->post_title, $b->post_title );
} );

// The loop
if ( $the_query->have_posts() ) :
    foreach ( $articles as $article ) {
        get_template_part( 'template-parts/content', 'archive-cchs_article', [ 'article' => $article ] );
    }
else :
    get_template_part( 'template-parts/content', 'none' );
endif;

In the above example inside the template part file instead of the_title() you would need to use echo $args['article']->post_title;.

The $args['article'] is the article we pass as 3rd argument in get_template_part function.

There is another approach: create post meta value with the title when the article is created or updated. This way we always have the final title saved and we can sort by it right away.

To do this hook to save_post, check if current post is an article and update the true_title meta value with custom field's value or with post title if that one is empty.

add_action( 'save_post', 'wpse_397145_save_proper_title', 10, 2 );

function wpse_397145_save_proper_title( $post_id, $post ) {
    // Only check in articles
    if ( 'cchs_article' !== $post->post_type ) {
        return;
    }

    // Set the final title to custom field, default to the post title
    $customTitle = get_post_meta( get_the_ID(), 'custom_title', true);
    if( ! $customTitle ) {
        $customTitle = $post->post_title;
    }
    update_post_meta( $post_id, 'true_title', $customTitle );
}

Now just change the WP_Query args to (you can even skip -1 here):

$args = array(
    'posts_per_page' => -1
    'post_type'      => 'cchs_article',
    'meta_key'       => 'true_title',
    'orderby'        => 'meta_value',
    'order'          => 'DESC'
);

And last, where you use the_title() for the article, replace it with echo get_post_meta( get_the_ID(), 'true_title', true); to output the correct title right away.

本文标签: Update some (not all) post titles with custom field values before running the Loop