Sample Custom Post Type

<?php
/**
 * Testimonials
 *
 * @package      CoreFunctionality
 * @author       Bill Erickson
 * @since        1.0.0
 * @license      GPL-2.0+
**/

class EA_CPT_Testimonial {

	/**
	 * Instance of the class.
	 *
	 * @since 1.0.0
	 *
	 * @var object
	 */
	private static $instance;

	/**
	 * Class Instance.
	 *
	 * @since 1.0.0
	 *
	 * @return EA_CPT_Testimonial
	 */
	public static function instance() {
		if ( ! isset( self::$instance ) && ! ( self::$instance instanceof EA_CPT_Testimonial ) ) {
			self::$instance = new EA_CPT_Testimonial();

			// Actions
			add_action( 'init',              array( self::$instance, 'register_tax'      )    );
			add_action( 'init',              array( self::$instance, 'register_cpt'      )    );
			add_action( 'gettext',           array( self::$instance, 'title_placeholder' )    );
			add_action( 'pre_get_posts',     array( self::$instance, 'testimonial_query' )    );
			add_action( 'template_redirect', array( self::$instance, 'redirect_single'   )    );

			// Column Filters
			add_filter( 'manage_edit-testimonial_columns',        array( self::$instance, 'testimonial_columns' )        );

			// Column Actions
			add_action( 'manage_testimonial_pages_custom_column', array( self::$instance, 'custom_columns'      ), 10, 2 );
			add_action( 'manage_testimonial_posts_custom_column', array( self::$instance, 'custom_columns'      ), 10, 2 );
		}
		return self::$instance;
	}
	
	/**
	 * Register the taxonomies
	 *
	 * @since 1.2.0
	 */
	function register_tax() {

		$taxonomies = [
			'testimonial_type' => [
				'singular_name' => 'Testimonial Type',
				'post_type'		=> [ 'testimonial' ],
			],
			'testimonial_topic' => [
				'singular_name' => 'Topic',
				'post_type'		=> [ 'testimonial' ],
			]
		];

		foreach( $taxonomies as $tax => $args ) {
			$singular_name	= !empty( $args['singular_name'] ) ? $args['singular_name'] : ucwords( str_replace( '_', ' ', $tax ) );
			$plural_name	= !empty( $args['plural_name'] ) ? $args['plural_name'] : $singular_name . 's';
			$hierarchical	= isset( $args['hierarchical'] ) ? $args['hierarchical'] : true;
			$rewrite		= !empty( $args['rewrite'] ) ? $args['rewrite'] : [ 'slug' => str_replace( '_', '-', $tax ), 'with_front' => false ];
			$admin_column	= isset( $args['show_admin_column'] ) ? $args['show_admin_column'] : true;
			$post_type		= !empty( $args['post_type'] ) ? $args['post_type'] : [ 'post' ];

			$labels = array(
		          'name'					=> $plural_name,
		          'singular_name'			=> $singular_name,
		          'search_items'			=> 'Search ' . $plural_name,
				  'popular_items'			=> 'Popular ' . $plural_name,
				  'all_items'				=> 'All ' . $plural_name,
				  'parent_item'				=> 'Parent ' . $singular_name,
				  'parent_item_colon'		=> 'Parent ' . $singular_name . ':',
				  'edit_item'				=> 'Edit ' . $singular_name,
				  'view_item'				=> 'View ' . $singular_name,
				  'update_item'				=> 'Update ' . $singular_name,
				  'add_new_item'			=> 'Add New ' . $singular_name,
				  'new_item_name'			=> 'New ' . $singular_name . ' Name',
				  'separate_items_with_commas' => 'Separate ' . $plural_name . ' with commas',
				  'add_or_remove_items'		=> 'Add or remove ' . $plural_name,
		      );

			$args = array(
				'labels'            => $labels,
				'public'            => true,
				'show_in_nav_menus' => true,
				'show_ui'           => true,
				'show_in_rest'      => true,
				'show_tagcloud'     => false,
				'hierarchical'      => $hierarchical,
				'rewrite'           => $rewrite,
				'query_var'         => true,
				'show_admin_column' => $admin_column,
				// 'meta_box_cb'    => false,
			);

			register_taxonomy( $tax, $post_type, $args );
		}
	}

	/**
	 * Register the custom post type
	 *
	 * @since 1.2.0
	 */
	function register_cpt() {

		$labels = array(
			'name'               => 'Testimonials',
			'singular_name'      => 'Testimonial',
			'add_new'            => 'Add New',
			'add_new_item'       => 'Add New Testimonial',
			'edit_item'          => 'Edit Testimonial',
			'new_item'           => 'New Testimonial',
			'view_item'          => 'View Testimonial',
			'search_items'       => 'Search Testimonials',
			'not_found'          => 'No Testimonials found',
			'not_found_in_trash' => 'No Testimonials found in Trash',
			'parent_item_colon'  => 'Parent Testimonial:',
			'menu_name'          => 'Testimonials',
		);

		$args = array(
			'labels'              => $labels,
			'hierarchical'        => false,
			'supports'            => array( 'title', 'editor', 'thumbnail' ),
			'public'              => true,
			'show_ui'             => true,
			'show_in_menu'        => true,
			'show_in_rest'        => true,
			'show_in_nav_menus'   => true,
			'publicly_queryable'  => true,
			'exclude_from_search' => false,
			'has_archive'         => true,
			'query_var'           => true,
			'can_export'          => true,
			'rewrite'             => array( 'slug' => 'testimonials', 'with_front' => false ),
			'menu_icon'           => 'dashicons-groups', // https://developer.wordpress.org/resource/dashicons/
		);

		register_post_type( 'testimonial', $args );

	}

	/**
	 * Change the default title placeholder text
	 *
	 * @since 1.2.0
	 * @global array $post
	 * @param string $translation
	 * @return string Customized translation for title
	 */
	function title_placeholder( $translation ) {

		global $post;
		if ( isset( $post ) && 'testimonial' == $post->post_type && 'Enter title here' == $translation ) {
			$translation = 'Enter Name Here';
		}
		return $translation;

	}

	/**
	 * Customize the Testimonials Query
	 *
	 * @since 1.2.0
	 * @param object $query
	 */
	function testimonial_query( $query ) {
		if( $query->is_main_query() && !is_admin() && $query->is_post_type_archive( 'testimonial' ) ) {
			$query->set( 'posts_per_page', 20 );
		}
	}

	/**
	 * Redirect Single Testimonials
	 *
	 * @since 1.2.0
	 */
	function redirect_single() {
		if( is_singular( 'testimonial' ) ) {
			wp_redirect( get_post_type_archive_link( 'testimonial' ) );
			exit;
		}
	}

	/**
	 * Testimonials custom columns
	 *
	 * @since 1.2.0
	 * @param array $columns
	 */
	function testimonial_columns( $columns ) {

		$columns = array(
			'cb'                  => '<input type="checkbox" />',
			'thumbnail'           => 'Thumbnail',
			'title'               => 'Name',
			'date'                => 'Date',
		);

		return $columns;
	}

	/**
	 * Cases for the custom columns
	 *
	 * @since 1.2.0
	 * @param array $column
	 * @param int $post_id
	 * @global array $post
	 */
	function custom_columns( $column, $post_id ) {

		global $post;

		switch ( $column ) {
			case 'thumbnail':
				the_post_thumbnail( 'thumbnail' );
				break;
		}
	}

}

/**
 * The function provides access to the class methods.
 *
 * Use this function like you would a global variable, except without needing
 * to declare the global.
 *
 * @since 1.0.0
 *
 * @return object
 */
function ea_cpt_testimonial() {
	return EA_CPT_Testimonial::instance();
}
ea_cpt_testimonial();
Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk