On This Page...
Last updated April 25th, 2023 at 05:51 pm
Websites like to display news
Many websites include an “In The News” section — content related to articles, videos, podcasts, etc., that other publishers have published about them. It might be called “News”, “Press”, “Media” or something else.
Here’s a screenshot of the “In The News” section of the wanderBOX website.
My Rule of Thumb Test for Custom Post Types:
An “In The News” post is a good use case for a custom post type. This is because it passes my rule-of-thumb test:
- All posts share a unique set of properties.
- You want to efficiently create and maintain these posts.
- You want to uniformly and consistently display these posts.
We can see from the above screenshot that there is a unique set of properties these posts share. They are Publication Name, Publication Date, Author Name, Article Title, and URL of the online article. There are also two “optional” properties: a brief description of the article, and an excerpt from the article.
When my client first started publishing In-The-News content, he created them as blog posts. By assigning these blog posts the category of “News”, we were able to isolate them so that they stood apart from all other blog posts.
Using the Blog Post Method Presents Problems…
But adding these news items as blog posts created a couple of problems:
Problem #1: Consistency
In order to display these posts consistently and uniformly, the authors had to remember exactly where to place the various “properties” as well as how each one is formatted.
Problem #2: Maintainability
What’s more, if the client decided at some time in the future that, for example, all the author names should be displayed differently (different font size, weight, or style; different color; etc.), then someone would have to go back into each “in The News” blog post and make the appropriate changes.
Converting to Custom Post Type
Because of these issues — and because “In The News” content is a perfect use case for a Custom Post Type — I recently converted all the “In The News” posts to posts of the custom post type “News”.
The code for registering the News CPT and the custom taxonomies for the News CPT are in a file named cpt-news.php and stored in the /mu-plugins/ folder.
Register Custom Post Type Code
Here is the code for registering the CPT:
function wb_register_news_cpt() { $labels = array( 'name' => _x( 'News Post', 'Post Type General Name', 'news_domain' ), 'singular_name' => _x( 'News Posts', 'Post Type Singular Name', 'news_domain' ), 'menu_name' => __( 'News', 'news_domain' ), 'name_admin_bar' => __( 'News', 'news_domain' ), 'archives' => __( 'News Archives', 'news_domain' ), 'attributes' => __( 'News Attributes', 'news_domain' ), 'parent_item_colon' => __( 'Parent Item:', 'news_domain' ), 'all_items' => __( 'All News Items', 'news_domain' ), 'add_new_item' => __( 'Add New News Item', 'news_domain' ), 'add_new' => __( 'Add New', 'news_domain' ), 'new_item' => __( 'New News Item', 'news_domain' ), 'edit_item' => __( 'Edit News Item', 'news_domain' ), 'update_item' => __( 'Update News Item', 'news_domain' ), 'view_item' => __( 'View News Item', 'news_domain' ), 'view_items' => __( 'View News Items', 'news_domain' ), 'search_items' => __( 'Search News Items', 'news_domain' ), 'not_found' => __( 'Not found', 'news_domain' ), 'not_found_in_trash' => __( 'Not found in Trash', 'news_domain' ), 'featured_image' => __( 'Featured Image', 'news_domain' ), 'set_featured_image' => __( 'Set featured image', 'news_domain' ), 'remove_featured_image' => __( 'Remove featured image', 'news_domain' ), 'use_featured_image' => __( 'Use as featured image', 'news_domain' ), 'insert_into_item' => __( 'Insert into News', 'news_domain' ), 'uploaded_to_this_item' => __( 'Uploaded to this News Item', 'news_domain' ), 'items_list' => __( 'News list', 'news_domain' ), 'items_list_navigation' => __( 'News list navigation', 'news_domain' ), 'filter_items_list' => __( 'Filter News list', 'news_domain' ), ); $args = array( 'label' => __( 'News', 'news_domain' ), 'description' => '', 'labels' => $labels, 'supports' => array( 'title', 'page-attributes' ), 'taxonomies' => array( 'news_cats', 'news_tags' ), 'hierarchical' => true, '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( 'news', $args ); } add_action( 'init', 'wb_register_news_cpt', 0 );
Register Custom Taxonomies Code
Here is the code for registering the news_cats taxonomy:
function wb_register_news_cats() { $labels = array( 'name' => _x( 'News Categories', 'Taxonomy General Name', 'text_domain' ), 'singular_name' => _x( 'News Category', 'Taxonomy Singular Name', 'text_domain' ), 'menu_name' => __( 'News Categories', 'text_domain' ), 'all_items' => __( 'All News Categories', 'text_domain' ), 'parent_item' => __( 'Parent Item', 'text_domain' ), 'parent_item_colon' => __( 'Parent Item:', 'text_domain' ), 'new_item_name' => __( 'New News Category Name', 'text_domain' ), 'add_new_item' => __( 'Add New News Category', 'text_domain' ), 'edit_item' => __( 'Edit News Category', 'text_domain' ), 'update_item' => __( 'Update News Category', 'text_domain' ), 'view_item' => __( 'View News Category', 'text_domain' ), 'separate_items_with_commas' => __( 'Separate News Categories with commas', 'text_domain' ), 'add_or_remove_items' => __( 'Add or remove News Categories', 'text_domain' ), 'choose_from_most_used' => __( 'Choose from the most used', 'text_domain' ), 'popular_items' => __( 'Popular News Categories', 'text_domain' ), 'search_items' => __( 'Search News Catetories', 'text_domain' ), 'not_found' => __( 'Not Found', 'text_domain' ), 'no_terms' => __( 'No News Categories', 'text_domain' ), 'items_list' => __( 'News Categories list', 'text_domain' ), 'items_list_navigation' => __( 'News Categories list navigation', 'text_domain' ), ); $args = array( 'labels' => $labels, 'hierarchical' => true, 'public' => true, 'show_ui' => true, 'show_admin_column' => true, 'show_in_nav_menus' => true, 'show_tagcloud' => true, ); register_taxonomy( 'news_cats', array( 'news' ), $args ); } add_action( 'init', 'wb_register_news_cats', 0 );
Here is the code for registering the news_tags taxonomy:
function wb_register_news_tags() { $labels = array( 'name' => _x( 'News Tags', 'Taxonomy General Name', 'text_domain' ), 'singular_name' => _x( 'News Tag', 'Taxonomy Singular Name', 'text_domain' ), 'menu_name' => __( 'News Tags', 'text_domain' ), 'all_items' => __( 'All News Tags', 'text_domain' ), 'parent_item' => __( 'Parent News Tag', 'text_domain' ), 'parent_item_colon' => __( 'Parent News Tag:', 'text_domain' ), 'new_item_name' => __( 'New News Tag', 'text_domain' ), 'add_new_item' => __( 'Add New News Tag', 'text_domain' ), 'edit_item' => __( 'Edit News Tag', 'text_domain' ), 'update_item' => __( 'Update News Tag', 'text_domain' ), 'view_item' => __( 'View News Tag', 'text_domain' ), 'separate_items_with_commas' => __( 'Separate News Tags with commas', 'text_domain' ), 'add_or_remove_items' => __( 'Add or remove News Tags', 'text_domain' ), 'choose_from_most_used' => __( 'Choose from the most used', 'text_domain' ), 'popular_items' => __( 'Popular News Tags', 'text_domain' ), 'search_items' => __( 'Search News Tags', 'text_domain' ), 'not_found' => __( 'Not Found', 'text_domain' ), 'no_terms' => __( 'No News Tags', 'text_domain' ), 'items_list' => __( 'News Tag list', 'text_domain' ), 'items_list_navigation' => __( 'News Tag list navigation', 'text_domain' ), ); $args = array( 'labels' => $labels, 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_admin_column' => true, 'show_in_nav_menus' => true, 'show_tagcloud' => true, ); register_taxonomy( 'news_tags', array( 'news' ), $args ); } add_action( 'init', 'wb_register_news_tags', 0 );
How the Posts are Added and Edited
Using Advanced Custom Fields Pro (but the free version would have sufficed for this implementation), I created a form group for “News”. News items are added and edited from the WordPress back end using this form, based on that form group:
How the Posts Display on the Website Front End
The nature of these “In The News” posts obviates the need for single post pages. Therefore, the only code that matters is that which renders the News archive.
All of the code that follows in this section is in a file named cpt-news-functions.php in the /mu-plugins/ folder.
Main Rendering Code
<?php function wb_news_render_archive() { if ( ! ( is_post_type_archive( 'news' ) || is_tax('news_cats') || is_tax('news_tags') ) ) return; /* Call */ $data = wb_news_get_single(get_the_ID()); extract($data); $pub_date_cos = date('F j, Y', strtotime($data['publication_date'])); /* Assemble the Categoy Links */ $cats = $data['news_cat_terms']; /* md array of term stuff for link_cats */ /* Assemble Category Archive permalinks (for THIS post) into an array that will be imploded for the nav */ $news_cats_archives = array(); foreach ( $cats as $cat ) { $news_cats_archives[] = '<a href="/' . $cat->taxonomy . '/' . $cat->slug . '/">' . $cat->name . '</a>'; } $news_cats_archives_nav = '<span class="terms">' . implode(' | ', $news_cats_archives) . '</span>'; ?> <div class="news-item-container"> <div class="publication-name"> <?php echo $data['publication_name'];?> </div> <div class="news-item"> <div class="article-title"> <?php echo $data['article_title'];?> </div> <div class="publication-date"> <span class="prompt">Date Published: </span> <?php echo $pub_date_cos;?> </div> <div class="author-name"> <span class="prompt">Author: </span> <?php echo $data['author_name'];?> </div> <?php if ( $data['about_this_article'] ) : ?> <div class="about-this-article"> <span class="prompt">About this article: </span> <span class="text"><?php echo $data['about_this_article'];?></span> </div> <?php endif; ?> <?php if ( $data['money_quote'] ) : ?> <div class="money-quote"> <span class="prompt">Excerpt: </span> <blockquote><?php echo $data['money_quote'];?></blockquote> </div> <?php endif; ?> <?php if ( !empty($cats) ) : ?> <nav class="cat-links"> <span class="prompt">Filed Under: </span> <?php echo $news_cats_archives_nav;?> </nav> <?php endif; ?> <div class="article-url"> <?php echo $data['article_url'];?> </div> <div class="permalink"> <a class="external button" target="_blank" title="Visit <?php echo $article_url;?>" href="<?php echo $article_url;?>">Read More >></a> </div> </div> </div><!-- / .news-item-container --> <?php } add_action('generate_after_entry_title', 'wb_news_render_archive');
Getting the Data for Each Individual “In The News” Post
Here is the code for retrieving the data for each individual News item. This function is called on line 6 of the above code. Notice that even though I’m using Advanced Custom Fields to generate the custom fields, I’m using the native WordPress get_post_meta()
function instead of ACF’s the_field()
function. I do this to avoid problems in the event that the ACF plugin is ever removed from the website. If the plugin were to be removed, all the “post_meta” content would remain in the database, but any code using ACF functions would fail.
<?php function wb_news_get_single($id) { $data = array(); // init $data['news_cat_terms'] = wp_get_post_terms($id, 'news_cats', array('fields' => 'all')); $data['news_tag_terms'] = wp_get_post_terms($id, 'news_tags', array('fields' => 'all')); $data['publication_name'] = get_post_meta($id, 'wbnews_publication_name', true); $data['publication_date'] = get_post_meta($id, 'wbnews_publication_date', true); $data['article_url'] = get_post_meta($id, 'wbnews_article_url', true); $data['article_title'] = get_post_meta($id, 'wbnews_article_title', true); $data['author_name'] = get_post_meta($id, 'wbnews_author_name', true); $data['money_quote'] = get_post_meta($id, 'wbnews_money_quote', true); $data['about_this_article'] = get_post_meta($id, 'wbnews_about_this_article', true); return $data; }
In Closing
I hope someone finds this post helpful. If you have questions, please ask in the comments section below. Thanks for listening.
Leave a Reply