megclaypool of Rootid
9/19/2019 - 11:27 PM

Custom Post Types / Content Types and Taxonomies in WordPress

How to create custom post types and taxonomies in WordPress

Create a new custom content type

WordPress.org Function Reference/register post type
WordPress.org Code Reference: register_post_type
Smashing: Extending WordPress with Custom Content Types
register_post_type( string $post_type, array|string $args = array() )

ex:

  if (!post_type_exists('person')) {
  
    // Set up all the labels to use for your content type
    $labels = array(
      'name'               => 'People',
      'singular_name'      => 'Person',
      'menu_name'          => 'People',
      'name_admin_bar'     => 'People',
      'add_new'            => 'Add New',
      'add_new_item'       => 'Add New Person',
      'new_item'           => 'New Person',
      'edit_item'          => 'Edit Person',
      'view_item'          => 'View Person',
      'all_items'          => 'All People',
      'search_items'       => 'Search People',
      'parent_item_colon'  => 'Parent Person',
      'not_found'          => 'No People Found',
      'not_found_in_trash' => 'No People Found in Trash'
    );

    // Set the permalink structure for your content type. 'with_front' is whether the permalink for your content type should be prepended with the front base. (example: if your permalink structure is /blog/, then your links will be: false->/news/, true->/blog/news/). Defaults to true
    $rewrite = [
      'slug'        => 'our-team',
      'with_front'  => false,
    ];

    // Features this content type supports in Post Editor
    $supports = [
      'title',
      'editor',
      'comments',
      'author',
      'thumbnail',
      'excerpt',
      'custom-fields',
      'revisions',
    ];

    // plug in all the arguments you just set up, along with a bunch more
    $args = [
      'labels'              => $labels,
      'rewrite'             => $rewrite,
      'supports'            => $supports,
      'public'              => true,
      'exclude_from_search' => false,
      'publicly_queryable'  => true,
      'show_ui'             => true,
      'show_in_nav_menus'   => true,
      'show_in_menu'        => true,
      'show_in_admin_bar'   => true,
      'menu_position'       => 4,
      'menu_icon'           => 'dashicons-groups',
      // note that any custom taxonomies need to be created, then added here
      'taxonomies'          => ['slugs', 'of', 'desired', 'taxonomies'],
      'capability_type'     => 'post',
      'hierarchical'        => false,
      'has_archive'         => false,
      'query_var'           => true,
      'show_in_rest'        => true,
    ];
    
    register_post_type('person', $args);
  }

Create a new custom taxonomy

WordPress.org: Function Reference/register taxonomy
WordPress.org: Code Reference -- register_taxonomy
Smashing: How To Create A Custom Taxonomy In WordPress
register_taxonomy( $taxonomy, $object_type, $args );
ex:

/**
 * Add 'role' taxonomy to the 'person' content type
 *
 * http://codex.wordpress.org/Function_Reference/register_taxonomy
 */
if (!taxonomy_exists('role')) {
  // This array of options controls the labels displayed in the WordPress Admin UI
  $labels = [
    'name'              => _x( 'Roles', 'taxonomy general name' ),
    'singular_name'     => _x( 'Roles', 'taxonomy singular name' ),
    'search_items'      => __( 'Search Locations' ),
    'all_items'         => __( 'All Locations' ),
    'parent_item'       => __( 'Parent Role' ),
    'parent_item_colon' => __( 'Parent Role:' ),
    'edit_item'         => __( 'Edit Role' ),
    'update_item'       => __( 'Update Role' ),
    'add_new_item'      => __( 'Add New Role' ),
    'new_item_name'     => __( 'New Role Name' ),
    'menu_name'         => __( 'Roles' ),
  ];

  // This array of options controls the slugs used for this taxonomy
  $rewrite = [
      // 'slug' controls the base slug that will display before each term
      'slug' => 'roles',
      // 'with_front controls whether to display the category base before "/roles/"
      'with_front' => false,
      // Whether to allow nested URLs like "/roles/employees/team-lead/"
      'hierarchical' => true
  ];

  $args = [
    // Hierarchical taxonomy (like categories)
    'hierarchical'      => true,
    'public'            => true,
    'show_admin_column' => true,
    'show_ui'           => true,
    'show_in_rest'      => true,
    'labels'            => $labels,
    'rewrite'           => $rewrite,
  ];

  register_taxonomy('role', 'person', $args);
}

Attach a pre-existing taxonomy (Categories or Tags) to a custom content type

When you create your custom content type, you need to include the following in the $args: 'taxonomies' => ['any', 'slugs', 'for', 'desired', 'taxonomies'],

ex: To add 'taxonomies' => ['category', 'post_tag', 'event_category', 'event_type'],

Important Note!!!

If you create a custom post type that shares tags or categories with posts, it's important to add that custom post type to the query for the tags/categories archive pages! Insipred by StackExchange:

/**
 * Show events on archive pages
 *
 * Because posts and events use common tags and
 * categories, we need to add events to the tags and
 * categories queries so they show up on those archive pages
 */
function radicati_include_events($query)
{
  if (($query->is_tag() || $query->is_category()) && $query->is_main_query()) {
    $query->set('post_type', array('post', 'event'));
  }
}

add_action('pre_get_posts', 'radicati_include_events');

Customize the columns of a content type admin page

Smashing: Customizing Admin Columns In WordPress
ex:

add_filter( 'manage_event_posts_columns', 'radicati_filter_events_columns' );

// set the columns to appear on the events admin page
function radicati_filter_events_columns( $columns ) {

  $columns = array(
    'cb' => $columns['cb'],
    'title' => __('Title'),
    'event_date' => __('Date', 'radicati'),
    'event_category' => __('Event Category', 'radicati'),
    'event_type' => __('Event Type', 'radicati'),
    'tags' => __('Tags', 'radicati'),
    'date' => __('Date Modified', 'radicati'),
    'author' => __('Author'),
  );

  return $columns;
}

// Add content to custom/non-standard columns
add_action('manage_event_posts_custom_column', 'radicati_event_column', 10, 2);

function radicati_event_column($column, $post_id)
{
  // Date column
  if ('event_date' === $column) {
    $date = get_post_meta($post_id, 'dates', true);

    if (!$date) {
      _e('n/a');
    } else {
      echo $date;
    }
  }
  // Event Category column
  if ('event_category' === $column) {
    $categories = get_the_term_list($post_id, 'event_category', null, ', ', null);

    if (!$categories) {
      _e('n/a');
    } else {
      echo $categories;
    }
  }
  // Event Type column
  if ('event_type' === $column) {
    $types = get_the_term_list($post_id, 'event_type', null, ', ', null);

    if (!$types) {
      _e('n/a');
    } else {
      echo $types;
    }
  }
}

// Make event date column sortable
add_filter('manage_edit-event_sortable_columns', 'radicati_event_sortable_columns');

function radicati_event_sortable_columns($columns)
{
  $columns['event_date'] = 'end_date';
  return $columns;
}

add_action('pre_get_posts', 'radicati_posts_orderby');
function radicati_posts_orderby($query)
{
  if (!is_admin() || !$query->is_main_query()) {
    return;
  }

  if ('end_date' === $query->get('orderby')) {
    $query->set('orderby', 'meta_value');
    $query->set('meta_key', 'end_date');
    $query->set('meta_type', 'numeric');
  }
}

Customize built-in 'Post' content type

ex:

// Change dashboard Posts to Articles
function wp_change_post_object()
{
  $get_post_type = get_post_type_object('post');

  $labels = (object) [
    'name' => 'Articles',
    'singular_name' => 'Article',
    'add_new' => 'Add New',
    'add_new_item' => 'Add New Article',
    'edit_item' => 'Edit Article',
    'new_item' => 'New Article',
    'view_item' => 'View Article',
    'view_items' => 'View Articles',
    'search_items' => 'Search Articles',
    'not_found' => 'No articles found.',
    'not_found_in_trash' => 'No articles found in Trash.',
    'parent_item_colon' => null,
    'all_items' => 'All Articles',
    'archives' => 'Article Archives',
    'attributes' => 'Article Attributes',
    'insert_into_item' => 'Insert into article',
    'uploaded_to_this_item' => 'Uploaded to this article',
    'featured_image' => 'Featured Image',
    'set_featured_image' => 'Set featured image',
    'remove_featured_image' => 'Remove featured image',
    'use_featured_image' => 'Use as featured image',
    'filter_items_list' => 'Filter articles list',
    'items_list_navigation' => 'Articles list navigation',
    'items_list' => 'Articles list',
    'item_published' => 'Article published.',
    'item_published_privately' => 'Article published privately.',
    'item_reverted_to_draft' => 'Article reverted to draft.',
    'item_scheduled' => 'Article scheduled.',
    'item_updated' => 'Article updated.',
    'menu_name' => 'Articles',
    'name_admin_bar' => 'Article',
  ];

  foreach($labels as $key => $value) {
    $get_post_type->labels->$key = $value;
  }

  $get_post_type->menu_icon = 'dashicons-welcome-write-blog';
}

Then call wp_change_post_object() inside the radicati_theme_init function