1

I have a custom post type "placement" with a custom field "position". What I want to do is, on the placements archive page, to order results by the "position" value.

I have the following URL rewrite rule:

$newRules['placements/?$'] = 'index.php?post_type=placement&meta_key=position&orderby=meta_value&order=DESC';

And this is how is defined my custom post type:

    function custom_post_type_placement() {

    $labels = array(
        'name'                => _x( 'Placements', 'Post Type General Name', 'text_domain' ),
        'singular_name'       => _x( 'Placement', 'Post Type Singular Name', 'text_domain' ),
        'menu_name'           => __( 'Placement', 'text_domain' ),
        'name_admin_bar'      => __( 'Placement', 'text_domain' ),
        'parent_item_colon'   => __( 'Parent Placement:', 'text_domain' ),
        'all_items'           => __( 'All Placements', 'text_domain' ),
        'add_new_item'        => __( 'Add New Placement', 'text_domain' ),
        'add_new'             => __( 'Add New', 'text_domain' ),
        'new_item'            => __( 'New Placement', 'text_domain' ),
        'edit_item'           => __( 'Edit Placement', 'text_domain' ),
        'update_item'         => __( 'Update Placement', 'text_domain' ),
        'view_item'           => __( 'View Placement', 'text_domain' ),
        'search_items'        => __( 'Search Placement', 'text_domain' ),
        'not_found'           => __( 'Not found', 'text_domain' ),
        'not_found_in_trash'  => __( 'Not found in Trash', 'text_domain' ),
    );
    $args = array(
        'label'               => __( 'Placement', 'text_domain' ),
        'description'         => __( 'Placements', 'text_domain' ),
        'labels'              => $labels,
        'supports'            => array( 'title', 'editor', ),
        'taxonomies'          => array( 'journal_placement' ),
        'hierarchical'        => false,
        'public'              => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'menu_position'       => 5,
        'show_in_admin_bar'   => true,
        'show_in_nav_menus'   => true,
        'can_export'          => true,
        'has_archive'         => true,      
        'exclude_from_search' => false,
        'publicly_queryable'  => true,
        'capability_type'     => 'page',
    );
    register_post_type( 'placement', $args );
add_action( 'init', 'custom_post_type_placement', 0 );

I am able to switch ASC and DESC correctly but my results are still ordered by post date.

Here is what the query looks like:

SELECT SQL_CALC_FOUND_ROWS fetr_posts.ID FROM fetr_posts WHERE 1=1 AND fetr_posts.post_type = 'placement' AND (fetr_posts.post_status = 'publish' OR fetr_posts.post_status = 'private') ORDER BY fetr_posts.post_date DESC LIMIT 0, 10

It seems the meta_key and orderby parameters are not taken into account. Do you have any idea why and how to sort my result properly using a rewrite rule ?


EDIT: thanks to Milo's answer, I changed my code the following way and it now works.

I removed completely the rewrite rule and defined my custom post as follow:

function custom_post_type_placement() {

    $labels = array(
        'name'                => _x( 'Placements', 'Post Type General Name', 'text_domain' ),
        'singular_name'       => _x( 'Placement', 'Post Type Singular Name', 'text_domain' ),
        'menu_name'           => __( 'Placement', 'text_domain' ),
        'name_admin_bar'      => __( 'Placement', 'text_domain' ),
        'parent_item_colon'   => __( 'Parent Placement:', 'text_domain' ),
        'all_items'           => __( 'All Placements', 'text_domain' ),
        'add_new_item'        => __( 'Add New Placement', 'text_domain' ),
        'add_new'             => __( 'Add New', 'text_domain' ),
        'new_item'            => __( 'New Placement', 'text_domain' ),
        'edit_item'           => __( 'Edit Placement', 'text_domain' ),
        'update_item'         => __( 'Update Placement', 'text_domain' ),
        'view_item'           => __( 'View Placement', 'text_domain' ),
        'search_items'        => __( 'Search Placement', 'text_domain' ),
        'not_found'           => __( 'Not found', 'text_domain' ),
        'not_found_in_trash'  => __( 'Not found in Trash', 'text_domain' ),
    );
    $rewrite = array(
        'slug'                => 'placements',
        'with_front'          => false,
        'pages'               => true,
        'feeds'               => false,
    );
    $args = array(
        'label'               => __( 'Placement', 'text_domain' ),
        'description'         => __( 'Placements', 'text_domain' ),
        'labels'              => $labels,
        'supports'            => array( 'title', 'editor', ),
        'taxonomies'          => array( 'journal_placement' ),
        'hierarchical'        => false,
        'public'              => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'menu_position'       => 5,
        'show_in_admin_bar'   => true,
        'show_in_nav_menus'   => true,
        'can_export'          => true,
        'has_archive'         => true,      
        'exclude_from_search' => false,
        'publicly_queryable'  => true,
        'rewrite'             => $rewrite,
        'capability_type'     => 'page',
    );
    register_post_type( 'placement', $args );

}
add_action( 'init', 'custom_post_type_placement', 0 );

and I also added this function:

function order_by_position($query){

    if(is_post_type_archive( 'placement' )){
        $query->query_vars['meta_key']="position";
        $query->query_vars['orderby']="meta_value_num";
    }
    return $query;
}

add_action( 'pre_get_posts', 'order_by_position' );

1 Answer 1

1

If your post type slug is placement, and you set has_archive to true, then the archive WordPress generates is at /placement/. Set has_archive to placements instead and let WordPress add the rewrite rules (which will also handle pagination properly).

Then, to order by your meta key, add a function hooked to pre_get_posts, check if the query is_main_query() and is_post_type_archive( 'placement' ), then set your meta_query parameters there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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