Merge two custom post types into one admin page?

I am building a site with 4 custom post types.
To make things easier for our client/admin, I’m wondering if there is a way to merge those custom post types into one list in the backend? Like if you look at normal backend admin page with the list and columns of posts, can a page like that pull in 3 other post types for easy sorting/searching?

I can’t combine the CPTs into one, they must remain seperate outside of one ‘viewing’ page in the admin area if possible.

Read More

Any thoughts on how to do this?? Or even where to start looking/thinkging of how to develop this?

Related posts

3 comments

  1. Just a starting point, as surely issues will popup during further development. For example, right now, the search functionality breaks as it expects a string (post_type) and it’s receiving an array.

    To list more than one post type in the Posts screen, we hook into pre_get_posts and modify the query. In this test, Posts, Pages and Products will be shown together in the Posts screen (http://example.com/wp-admin/edit.php).

    add_action( 'pre_get_posts', 'join_cpt_list_wspe_113808' );
    
    function join_cpt_list_wspe_113808( $query ) 
    {
        // If not backend, bail out
        if( !is_admin() )
            return $query;
    
        // Detect current page and list of CPTs to be shown in Dashboard > Posts > Edit screen
        global $pagenow;
        $cpts = array( 'post', 'page', 'product' );
    
        if( 'edit.php' == $pagenow && ( get_query_var('post_type') && 'post' == get_query_var('post_type') ) )
            $query->set( 'post_type', $cpts );
    
        return $query;
    }
    

    A helper code to show a column with each post Post Type:

    add_filter( 'manage_edit-post_columns', 'add_cpt_column_wspe_113808' );
    foreach( array( 'post', 'page', 'product' ) as $cpt )
        add_action( "manage_{$cpt}_posts_custom_column", 'show_cpt_column_wspe_113808', 10, 2 );
    
    function add_cpt_column_wspe_113808( $columns ) 
    {
        $columns[ 'cpt' ] = 'Post Type';
        return $columns;
    }
    
    function show_cpt_column_wspe_113808( $column_name, $post_id ) 
    {
        if ( 'cpt' != $column_name )
            return;
        echo get_post_type( $post_id );
    }
    
  2. I’d recommend Admin Menu Editor pro for this. I’ll link to it at the bottom.

    Interesting. On a certain project I was working on I had several CPTs (custom post types) that were kind of related. The section was ‘Info Center’ and they wanted Press Releases, White Papers, Testimonials etc. to be within Info center. On the front end, creating this was easy. On the back end we wanted it to logically fit together, too. Most of the Custom Post Types were set as CPTs due to specific content (meta fileds) and layout requirements. We ended up having, like, close to 20 CPTs.

    That said, we used the admin editor plugin to remove the related Info Center CPTs from the back end menu and then Created an ‘Info Center’ menu with the related CPT links within. While they all seemed combined, they weren’t.

    Here’s the plugin link: http://adminmenueditor.com/ try out the demo, too.

  3. For anyone still looking at this problem – brasofilo’s solution is great but some functions are won’t work (search, number of posts per page, bulk actions etc.). A solution: instead of hooking into pre_get_posts you should modify the sql query by hooking into posts_where. Here is example of code that does the job for me:

    add_filter( 'posts_where', 'mirmic_search_where' );
    function mirmic_search_where( $where ) {
        global $pagenow, $wpdb;
        
        if( 'edit.php' == $pagenow && ( get_query_var('post_type') && 'wszystkieposty' == get_query_var('post_type') ) ) {
            $stringToReplace = "trnf_posts.post_type = 'wszystkieposty'";
            $replaceWith = "trnf_posts.post_type IN ('infobus', 'infoair', 'inforail', 'infotram', 'infoship', 'infoair', 'infobike')";
            $where = str_replace($stringToReplace, $replaceWith, $where );
        }
        return $where;
    }
    
    
    function mirmic_wszystkieposty_distinct( $where ){
        global $pagenow, $wpdb;
    
        if ( is_admin() && $pagenow=='edit.php' && $_GET['post_type']=='wszystkieposty') {
            return "DISTINCT";
        }
        return $where;
    }
    add_filter( 'posts_distinct', 'mirmic_wszystkieposty_distinct' );
    

    The slug of custom post type to show other post types is wszystkieposty. Change it accordingly.
    Other post types to show are listed in this line:

    $replaceWith = "trnf_posts.post_type IN ('infobus', 'infoair', 'inforail', 'infotram', 'infoship', 'infoair', 'infobike')";
    

Comments are closed.