Skip to content

Instantly share code, notes, and snippets.

@krystyna93
Last active June 10, 2023 14:51
Show Gist options
  • Save krystyna93/e909a5d50e96ed237a10b5eb7bb1d976 to your computer and use it in GitHub Desktop.
Save krystyna93/e909a5d50e96ed237a10b5eb7bb1d976 to your computer and use it in GitHub Desktop.
Custom WordPress Metabox: Relationship Between Two CPT's
<?php
/*
a general overview of how to create a WordPress metabox that establishes a relationship between two custom post types and shares
details between them both, then output the data to the front end.
You will need to first register your custom post types using the register_post_type() function in your WordPress theme's functions.php
file.
Create a metabox for one of the custom post types using the add_meta_box() function. Within the metabox callback function
you can use the metadata API to retrieve data related to the other custom post type.
Use a custom field to store the relationship between the two custom post types.
This can be done using the add_post_meta() and update_post_meta() functions.
Retrieve the related data from the other custom post type using the get_posts() function and the meta_query parameter to filter
by the custom field value. You can also use WP_Query to retrieve posts and filter them based on custom field values.
Output the related data in the metabox using HTML and/or PHP.
To display the data on the front end, you can create a custom template for your custom post type or use a shortcode to display
the related data on a post or page.
For example, let's say you have two custom post types: "Books" and "Authors". You want to establish a relationship between them so
that each book can have one author and each author can write multiple books. Here's how you might set this up:
Register the custom post types In your functions.php file, register the "Books" custom post type:
*/
function create_books_post_type() {
$args = array(
'labels' => array(
'name' => __( 'Books' ),
'singular_name' => __( 'Book' )
),
'public' => true,
'has_archive' => true,
'supports' => array( 'title', 'editor', 'thumbnail' )
);
register_post_type( 'books', $args );
}
add_action( 'init', 'create_books_post_type' );
/*Then, register the "Authors" custom post type: */
function create_authors_post_type() {
$args = array(
'labels' => array(
'name' => __( 'Authors' ),
'singular_name' => __( 'Author' )
),
'public' => true,
'has_archive' => true,
'supports' => array( 'title', 'editor', 'thumbnail' )
);
register_post_type( 'authors', $args );
}
add_action( 'init', 'create_authors_post_type' );
/* Create a metabox for the "Books" custom post type Create a metabox for the "Books" custom post type using the add_meta_box()
function. Within the metabox callback function, use the metadata API to retrieve data related to the "Authors" custom post type.*/
function books_author_metabox() {
add_meta_box(
'books-author-metabox',
__( 'Author Details' ),
'books_author_metabox_callback',
'books'
);
}
add_action( 'add_meta_boxes', 'books_author_metabox' );
function books_author_metabox_callback( $post ) {
// Add a nonce field to the books author metabox
wp_nonce_field( basename( __FILE__ ), 'books_author_nonce' );
// Retrieve the author ID from the custom field
$author_id = get_post_meta( $post->ID, 'book_author', true );
// Retrieve the author name from the "Authors" custom post type
$author_name = '';
if ( $author_id ) {
$author_post = get_post( $author_id );
$author_name = $author_post->post_title;
}
// Output the author name in the metabox
echo 'Author: ' . $author_name;
// Add a select dropdown for choosing the author
$args = array(
'post_type' => 'authors',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
);
$authors = get_posts( $args );
echo '<label for="book_author">Select Author:</label>';
echo '<select name="book_author">';
echo '<option value="">-- Select --</option>';
foreach ( $authors as $author ) {
$selected = '';
if ( $author->ID == $author_id ) {
$selected = 'selected';
// Add the selected attribute if the author is already set for the book
echo '<option value="' . $author->ID . '" ' . $selected . '>' . $author->post_title . '</option>';
}
echo '</select>';
}
/*
Use a custom field to store the relationship between the two custom post types Add a custom field to the "Books" custom post type
to store the relationship between the book and author. You can use the add_post_meta() function to add the custom field, and the
update_post_meta() function to update it.
*/
function save_books_author_metabox( $post_id ) {
// Verify the nonce before saving data
if ( !isset( $_POST['books_author_nonce'] ) || !wp_verify_nonce( $_POST['books_author_nonce'], basename( __FILE__ ) ) ) {
return $post_id;
}
// Save the author ID to the custom field
if ( isset( $_POST['book_author'] ) ) {
$author_id = sanitize_text_field( $_POST['book_author'] );
update_post_meta( $post_id, 'book_author', $author_id );
}
}
add_action( 'save_post_books', 'save_books_author_metabox' );
/*
Retrieve the related data from the "Authors" custom post type Retrieve the related data from the "Authors" custom post type
using the get_posts() function and the meta_query parameter to filter by the custom field value.
*/
function get_books_by_author( $author_id ) {
$args = array(
'post_type' => 'books',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'book_author',
'value' => $author_id,
),
),
);
$books = get_posts( $args );
return $books;
}
/*Output the related data in the metabox and on the front end Output the related data in the metabox using HTML and/or PHP.
To display the data on the front end, you can create a custom template for your custom post type or use a shortcode to display the
related data on a post or page.
For example, to display a list of books by an author on the front end, you could create a shortcode that accepts the author ID
as a parameter, then uses the get_books_by_author() function to retrieve the books and output them in a list.
*/
function books_by_author_shortcode( $atts ) {
$atts = shortcode_atts( array(
'author_id' => '',
), $atts );
$books = get_books_by_author( $atts['author_id'] );
if ( ! empty( $books ) ) {
echo '<ul>';
foreach ( $books as $book ) {
echo '<li>' . $book->post_title . '</li>';
}
echo '</ul>';
}
}
add_shortcode( 'books_by_author', 'books_by_author_shortcode' );
/*You can then use the [books_by_author] shortcode in any post or page, like this: */
[books_by_author author_id="123"]
/*This will display a list of books with the "book_author" custom field set to 123.
Additionally, if you want to display the related data on a custom template for your custom post type, you can create a new file
called single-books.php in your theme directory. This file will be used to display single entries of the "Books" custom post type.
Within this file, you can use the get_post_meta() function to retrieve the author ID from the custom field and then use
the get_post() function to retrieve the author name from the "Authors" custom post type. You can then output the author name
and any other related data within the template.
Here's an example single-books.php file:
*/
<?php get_header(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<article class="entry">
<header class="entry-header">
<h1 class="entry-title"><?php the_title(); ?></h1>
<?php
// Retrieve the author ID from the custom field
$author_id = get_post_meta( get_the_ID(), 'book_author', true );
// Retrieve the author name from the "Authors" custom post type
$author_name = '';
if ( $author_id ) {
$author_post = get_post( $author_id );
$author_name = $author_post->post_title;
}
?>
<p class="entry-meta">By <?php echo $author_name; ?></p>
</header>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
<?php endwhile; ?>
<?php get_footer();
/*
In this example, we retrieve the author ID from the "book_author" custom field using the get_post_meta() function,
and then use the get_post() function to retrieve the author name from the "Authors" custom post type.
We then output the author name within the entry header using PHP.
This is just one example of how you can display related data from two custom post types in WordPress.
The implementation may vary depending on your specific use case and requirements, but this should give you a general idea of
how to establish a relationship between two custom post types and output the related data in a metabox and on the front end. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment