Creating Custom Post Types, with Multiple Text Fields in a Single Meta Box and Template Info, in WordPress
Posted on October 31, 2015 in PHP, WordPress by Matt Jennings
Below are WordPress and PHP code samples on how to:
- Create custom post types using a plugin.
- Create multiple text fields (using
input
andtextarea
tags for example) using inside a single meta box to push a custom post type into the MySQL database. - Using various theme templates to have said custom post types appear on a:
- Page, including a limit to how posts can appear on said page template.
- Single post template.
Plugin Example found at /wp-content/plugins/wp-job-listing/wp-job-listing.php
<?php /** * Plugin Name: WP Job Listing * Plugin URI: http://hatrackmedia.com * Description: This plugin allows you to add a simple job listing section to your WordPress website. * Author: Bobby Bryant * Author URI: http://hatrackmedia.com * Version: 0.0.1 * License: GPLv2 */ // Exit if accessed directly if(!defined('ABSPATH')) { exit; } // Create a custom post type function dwwp_register_post_type() { $singular = 'Job Listing'; $plural = $singular . 's'; $labels = array( 'name' => $plural, 'singular_name' => $singular, 'add_name' => 'Add New', 'add_new_item' => 'Add New ' . $singular, 'edit' => 'Edit', 'edit_item' => 'Edit ' . $singular, 'new_item' => 'New ' . $singular, 'view' => 'View ' . $singular, 'view_item' => 'View' . $singular, 'search_term' => 'Search ' . $plural, 'parent' => 'Parent ' . $singular, 'not_found' => 'No ' . $plural . ' found', 'not_found_in_trash' => 'No ' . $plural . ' in Trash' ); $args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'exclude_from_search' => false, 'show_in_nav_menus' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_admin_bar' => true, 'menu_position' => 6, 'menu_icon' => 'dashicons-businessman', 'can_export' => true, 'delete_with_user' => false, 'hierarchical' => false, // Use this is post type doesn't need archive page 'has_archive' => false, 'query_var' => true, 'capability_type' => 'post', 'map_meta_cap' => true, 'rewrite' => array( 'slug' => 'job-listings', 'with_front' => true, 'pages' => true, 'feeds' => true ), 'supports' => array( 'title', 'thumbnail' ) ); register_post_type('job', $args); } add_action('init', 'dwwp_register_post_type'); /** * Adds a box to the main column on the Post and Page edit screens. */ function job_listings_add_meta_box() { add_meta_box( 'jobs_listings_id', __( 'New Job', 'job_listings_plugin' ), 'jobs_listings_meta_box_callback', // This is the name of the custom post type, // does NOT need to 'slug' element of the // $args array above, // and must be only letter with no // special characters 'job' ); } function jobs_listings_meta_box_callback($post) { // Add a nonce field so we can check for it later. wp_nonce_field( 'myplugin_save_meta_box_data', 'myplugin_meta_box_nonce' ); $job_title_value = get_post_meta($post->ID, '_job_title', true); $job_salary_value = get_post_meta($post->ID, '_job_salary', true); echo '<p><label for="job_title">Title</label> <input type="text" name="job_title" id="' . $post->ID . '" value="' . $job_title_value . '" style="width: 100%;" /></p>'; echo '<p><label for="job_salary">Salary</label> <input type="text" name="job_salary" id="' . $post->ID . '" value="' . $job_salary_value . '" style="width: 100%;" /></p>'; } add_action( 'add_meta_boxes', 'job_listings_add_meta_box' ); function jobs_save_meta_box_data( $post_id ) { /* * We need to verify this came from our screen and with proper authorization, * because the save_post action can be triggered at other times. */ // Check if our nonce is set. if ( ! isset( $_POST['myplugin_meta_box_nonce'] ) ) { return; } // Verify that the nonce is valid. if ( ! wp_verify_nonce( $_POST['myplugin_meta_box_nonce'], 'myplugin_save_meta_box_data' ) ) { return; } // If this is an autosave, our form has not been submitted, so we don't want to do anything. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } /* OK, it's safe for us to save the data now. */ // Make sure that it is set. if ( !isset($_POST['job_title']) && !isset($_POST['job_salary']) ) { return; } // Sanitize user input. $my_data_job_title = sanitize_text_field( $_POST['job_title'] ); $my_data_job_salary = sanitize_text_field( $_POST['job_salary'] ); // Update the meta field in the database. update_post_meta( $post_id, '_job_title', $my_data_job_title ); update_post_meta( $post_id, '_job_salary', $my_data_job_salary ); } add_action( 'save_post', 'jobs_save_meta_box_data' );
/job-listings
page template in a file called /wp-content/themes/twentyfifteen/job-listings.php
that Lists All of the Job Listings Custom Post Types from Plugin Above
<?php /* Template Name: Job Listings */ /** * The template for displaying pages * * This is the template that displays all pages by default. * Please note that this is the WordPress construct of pages and that * other "pages" on your WordPress site will use a different template. * * @package WordPress * @subpackage Twenty_Fifteen * @since Twenty Fifteen 1.0 */ get_header(); ?> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php $args = array( 'post_type' => 'job', 'orderby' => 'title', 'order' => 'asc', 'posts_per_page' => 3 ); $lib_query = new WP_Query($args); if ($lib_query->have_posts()) { while ($lib_query->have_posts()) : $lib_query->the_post(); $img_src = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID)); ?> <div class="single-job"> <p><strong><a href="<?php the_permalink(); ?>">_job_title:</strong> <?php echo get_post_meta($post->ID, '_job_title', true); ?></a></p> <p><strong>_job_salary:</strong> <?php echo get_post_meta($post->ID, '_job_salary', true); ?></p> <p><strong>Single Image:</strong><br /><?php echo get_the_post_thumbnail(); ?></p> <p><strong>Background Image:</strong></p> <p style="background: url(<?php echo $img_src[0]; ?>); height: 100px;"></p> </div> <?php endwhile; wp_reset_postdata(); } ?> </main><!-- .site-main --> </div><!-- .content-area --> <?php get_footer(); ?>
Single Job Listings Post Template in a file called /wp-content/themes/twentyfifteen/single-job.php
<?php /* Template Name: Single Job Listings Post Template */ /** * The template for displaying pages * * This is the template that displays all pages by default. * Please note that this is the WordPress construct of pages and that * other "pages" on your WordPress site will use a different template. * * @package WordPress * @subpackage Twenty_Fifteen * @since Twenty Fifteen 1.0 */ get_header(); ?> <div class="list-container"> <h1>Single Job Listings Post Template</h1> <?php // Start the loop. while ( have_posts() ) : the_post(); $img_src = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID)); ?> <div class="single-job"> <p><strong><a href="<?php the_permalink(); ?>">_job_title:</strong> <?php echo get_post_meta($post->ID, '_job_title', true); ?></a></p> <p><strong>_job_salary:</strong> <?php echo get_post_meta($post->ID, '_job_salary', true); ?></p> <p><strong>Single Image:</strong><br /><?php echo get_the_post_thumbnail(); ?></p> <p><strong>Background Image:</strong></p> <p style="background: url(<?php echo $img_src[0]; ?>); height: 100px;"></p> </div> <?php // End the loop. endwhile; ?> </div> <?php get_footer(); ?>
Code in /wp-content/themes/twentyfifteen/functions.php
that Enables the single-job.php
Template Above to Work and Enable Thumbnail Support for Said Custom Post Types
// Get Custom Post Type Template for a Single Post function my_single_template($single) { if(file_exists(get_template_directory() . '/single-' . get_the_ID() . '.php')) return get_template_directory() . '/single-' . get_the_ID() . '.php'; return $single; } add_filter('single_template', 'my_single_template'); /* * Enable support for Post Thumbnails on posts and pages. * * See: https://codex.wordpress.org/Function_Reference/add_theme_support#Post_Thumbnails */ add_theme_support( 'post-thumbnails' );
Code to add in the Custom Structure
field, after Logging in the WordPress Admin and going to Settings > Permalinks
and choosing the Custom Structure
radio button
/%category%/%postname%/