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
inputandtextareatags 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%/