I hope this question has its place here.

I've always thought that connecting different Custom Post Types together is a rather common need, like in popular tutorial examples of custom taxonomy usage (books/authors/titles, films/actors/directors, etc). I personally use "Posts 2 Posts", but support stopped.

On Google the most relevant results point to this plugin right now. Which long term alternatives exist? What would a seasoned WordPress web developer use to design a book/author/title management system with WordPress today, if P2P plugin is finished?

  • What code did you use to create the custom post types? You can add support for creating custom taxonomy types using this code wordpress.stackexchange.com/a/128544/9884 Commented Jan 12, 2014 at 23:07
  • 1
    I think a huge number of people still use p2p so I can't see it failing anytime soon as someone could just fork and maintain it on github. If support has been dropped however I assume it just means scribu is working on something new or the functionality may be making its way into core. I don't see it as a reason not to use it. Commented Jan 16, 2014 at 10:33
  • 1
    I'm not so sure sancho. P2P has only 55,000 downloads on WP plugins page, far less popular than I had thought. And I don't understand why, again because connecting CPTs together sounds to me like a very basic and common need. How can a plugin that solely addresses something so basic could have only 55,000 downloads? That's beyond me. The only explanation is that there's another good way to address it hence my question.
    – drake035
    Commented Jan 16, 2014 at 13:29
  • 3
    You could continue to use this plugin and if the plugin should fail somehow, you could fork the repo and maintain it yourself: github.com/scribu/wp-posts-to-posts.git Quote from the repo: If you want to help maintain the plugin, fork it on github and open pull requests.
    – Scuba Kay
    Commented Jan 17, 2014 at 8:29
  • 4
    Upvoted and starred this question because I think HABTM in WordPress is really interesting. That said, I wouldn't sweat the plugin going away too much, Mark Jaquith has volunteered to help keep it going. And while some WP plugins may have 300000 downloads or whatever, not many have 472 stars on github. For keeping it alive, that's the number that counts!
    – Will
    Commented Jan 19, 2014 at 3:51

3 Answers 3


As a programmer, I would start writing my own code to connect my post types. It's not a quick way, it's not easy, but it's a lot of fun.

The post types

We start by creating two simple post types, Author and Books:

add_action('init', 'p2p2_register_author');
add_action('init', 'p2p2_register_book');

function p2p2_register_author(){
    $labels = array(
        'name'               => 'Author',
        'singular_name'      => 'Author',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Author',
        'edit_item'          => 'Edit Author',
        'new_item'           => 'New Author',
        'all_items'          => 'All Authors',
        'view_item'          => 'View Authors',
        'search_items'       => 'Search Authors',
        'not_found'          => 'No authors found',
        'not_found_in_trash' => 'No authors found in Trash',
        'parent_item_colon'  => '',
        'menu_name'          => 'Authors'

        array (
            'labels'             => $labels,
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => array( 'slug' => 'author' ),
            'capability_type'    => 'post',
            'has_archive'        => true,
            'hierarchical'       => false,
            'menu_position'      => null,
            'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
function p2p2_register_book(){
    $labels = array(
        'name'               => 'Books',
        'singular_name'      => 'Book',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Book',
        'edit_item'          => 'Edit Book',
        'new_item'           => 'New Book',
        'all_items'          => 'All Books',
        'view_item'          => 'View Book',
        'search_items'       => 'Search Books',
        'not_found'          => 'No books found',
        'not_found_in_trash' => 'No books found in Trash',
        'parent_item_colon'  => '',
        'menu_name'          => 'Books'

        array (
            'labels'             => $labels,
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => array( 'slug' => 'book' ),
            'capability_type'    => 'post',
            'has_archive'        => true,
            'hierarchical'       => false,
            'menu_position'      => null,
            'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )

Nothing fancy there. In fact, it's from the Codex!

The metabox

Let's continue by adding a metabox for our author to our book post type:

add_action('admin_init', 'p2p2_add_author_metabox');

function p2p2_add_author_metabox(){
        __('Book Author', 'bandpress'), 
        array( 'id' => 'p2p2_author') 

Here you can see a callback function p2p2_book_author_metabox which is going to be what's inside our metabox.

The content of the metabox

Let's create the function:

function p2p2_book_author_metabox($post, $args){
    wp_nonce_field( plugin_basename( __FILE__ ), 'p2p2_book_author_nonce' );
    $author_id = get_post_meta($post->ID, 'p2p2_book_author', true);

    echo "<p>Select the author of the book</p>";
    echo "<select id='p2p2_book_author' name='p2p2_book_author'>";
    // Query the authors here
    $query = new WP_Query( 'post_type=author' );
    while ( $query->have_posts() ) {
        $id = get_the_ID();
        $selected = "";

        if($id == $author_id){
            $selected = ' selected="selected"';
        echo '<option' . $selected . ' value=' . $id . '>' . get_the_title() . '</option>';
    echo "</select>";

Here's where the magic happens. First we're going to query the database for authors and then we fill a <select> with our query results. Check the Codex for more about WP_Query. Now you can go to your book post type and see your dropdown:

Our dropdown

Saving our content

Off course we want to save our selection so we add another function that's going to save the metabox for us:

add_action('save_post', 'p2p2_save_author_metabox', 1, 2);

function p2p2_save_author_metabox($post_id, $post){
    // Don't wanna save this now, right?
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
    if ( !isset( $_POST['p2p2_book_author_nonce'] ) )
    if ( !wp_verify_nonce( $_POST['p2p2_book_author_nonce'], plugin_basename( __FILE__ ) ) )

    // We do want to save? Ok!
    $key = 'p2p2_book_author';
    $value = $_POST["p2p2_book_author"];
    if ( get_post_meta( $post->ID, $key, FALSE ) ) { // If the custom field already has a value
        update_post_meta( $post->ID, $key, $value );
    } else { // If the custom field doesn't have a value
        add_post_meta( $post->ID, $key, $value );
    if ( !$value ) delete_post_meta( $post->ID, $key ); // Delete if blank

Now go and save a book with an author! The author of the book will be saved in the wp_postmeta database table and the selected value of the dropdown will be that in the meta.

An author column for book

Let's expand the admin area for our books. We will start by changing the columns:

add_filter('manage_edit-book_columns', 'p2p2_add_book_columns');

function p2p2_add_book_columns($columns){
    $new_columns['cb'] = '<input type="checkbox" />';

    $new_columns['title'] = _x('Title', 'column name', 'bandpress');

    $new_columns['p2p2_author'] = __('Author', 'bandpress');

    return $new_columns;

This function makes sure we only see the columns title and p2p2_author. The cb checkbox column is needed for WordPress' mass edit functionality. Now we need to add some information to our column. We add this function:

add_action('manage_book_posts_custom_column', 'p2p2_fill_book_columns', 10, 2);

function p2p2_fill_book_columns($column_name, $id) {
    global $wpdb;
    switch ($column_name) {
        case 'p2p2_author':
            $author_id = get_post_meta($id, 'p2p2_book_author', true);
            $author = get_post($author_id);
            $permalink = get_permalink($author_id);
            echo "<a href='" . $permalink . "'>" . $author->post_title . "</a>";
    } // end switch

The switch is for every column you just added in the previous function. You fill it by echoing what you want to show. We get the post that's the author of our book and create a nice permalink to his/her 'profile page'. This is what it looks like:

Our author column

To be continued

We connected two post types in the backend of our WordPress site, but we can't see a thing of it in the frontend. It'll need a lot more work to accomplish this, but the possibilities are somewhat endless. We could:

  1. Sort books by author
  2. Show a list of books on the author page
  3. Show a list of other books of the author on the book page
  4. Create a fancy metabox with pictures of the author
  5. Create a column in the author admin page for the books he/she wrote
  6. And a lot more...

I will continue working on this answer, as I need this solution myself. However, I will stop working on in for now. I'll start updating this answer tomorrow.

  • Thank you for sharing your amazing reply. How would you show a list of books written by the author ?
    – William
    Commented Oct 13, 2016 at 9:43

I wouldn't worry about it too much, as a couple of great developers volunteered to continue support. However, if you want to use something else check out the ACF relationship field.

  • Lone links and plugin recommendations are considered to be poor quality answers. The reason is simple: If the link is gone, the answer (and this site) suffers from link rot.
    – kaiser
    Commented Feb 9, 2014 at 12:29
  • 3
    Link-free solutions can become obsolete over time too, and this is worst than dead links because some people may waste time trying to implement these obsolete solutions not knowing they don't work anymore. Besides ACF and its website are likely to last a very long time. Finally thanks a lot Bjorn for this fantastic alternative.
    – drake035
    Commented Mar 22, 2014 at 22:59

Since the original question is "What would you do if P2P went away?" I have a thought/suggestion. I actually needed, because if you're building a plugin, telling users to install another plugin isn't always viable.

One simple method would be to use the Post Meta. For example. In the post_meta of Author, you can store the books. Either as unique entries or a single comma separated entry or a serialized array. Then on the book, you store the inverse info of Author(s).

Another would be to add a new DB table (frowned upon) that stores the relationships and other pertinent information.

No idea how efficient either solution is at scale, but they work.

Your Answer

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

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