Use Custom Post Type as Custom Field

To get the posts from a post type you can use get_posts()

$posts = get_posts(
    array (
        'numberposts'    => -1,
        'posts_per_page' => -1,
        'post_type'      => 'store'
    )
);

Be aware, the -1 is dangerous: If there are millions of stores, the query might run into a time-out.

Here is a very basic example for such a meta box. You will find much more examples and explanations in our tag .

<?php # -*- coding: utf-8 -*-
/* Plugin Name: Store metabox */

add_action( 'add_meta_boxes_post', 'wpse_98184_register_store_metabox' );
add_action( 'save_post', 'wpse_98184_save_store_metabox' );

function wpse_98184_register_store_metabox()
{
    add_meta_box( 'post_store', 'Store', 'wpse_98184_render_store_metabox', NULL, 'side' );
}

function wpse_98184_render_store_metabox( $object, $box )
{
    $nonce = wp_create_nonce( __FILE__ );
    echo "<input type="hidden" name="nonce_store_mbox" value="$nonce" />";

    $posts = get_posts(
        array (
            'numberposts'    => -1,
            'posts_per_page' => -1,
            'post_type'      => 'store',
        )
    );

    if ( ! $posts )
        return print 'No store found';

    $meta    = get_post_meta( $object->ID, '_store', TRUE );
    $selected = $meta ? $meta : 0;
    $html="<select name="_store"><option value="0">Select a store</option>";

    foreach ( $posts as $post )
        $html .= sprintf(
            '<option value="%1$d" %2$s>%3$s</option>',
            esc_attr( $post->ID ),
            selected( $post->ID, $selected, FALSE ),
            esc_html( $post->post_title )
            );

    $html .= '</select>';

    echo $html;
}

function wpse_98184_save_store_metabox( $id )
{
    if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
        return;

    if ( ! isset ( $_POST[ 'nonce_store_mbox' ] ) )
        return;

    if ( ! wp_verify_nonce( $_POST[ 'nonce_store_mbox' ], __FILE__ ) )
        return;

    if ( ! current_user_can( 'edit_post', $id ) )
        return;

    if ( ! isset ( $_POST['_store'] ) )
        return delete_post_meta( $id, '_store' );

    update_post_meta( $id, '_store', $_POST['_store'] );
}

To list all these associated posts in a store page, use a function that queries for post meta fields:

function wpse_98184_list_store_posts()
{
    $args = array(
        'post_type'  => 'post',
        'numberposts'    => -1,
        'posts_per_page' => -1,
        'meta_query' => array (
            array (
                'key' => '_store',
                'value'   => get_the_ID(),
                'compare' => '==',
            ),
        )
    );

    $posts = get_posts( $args );

    if ( ! $posts )
        return '';

    $output="<ul class="store-posts">";

    foreach ( $posts as $post )
        $output .= sprintf(
            '<li><a href="https://wordpress.stackexchange.com/questions/98184/%1$s">%2$s</a></li>',
            get_permalink( $post->ID ),
            esc_html( get_the_title( $post->ID ) )
        );

    $output .= '</ul>';

    return $output;
}

You could use this function as a shortcode handler:

add_shortcode( 'storeposts', 'wpse_98184_list_store_posts' );

Then just add [storeposts] wherever you need that list in your store.

Leave a Comment