Creating Custom Input Forms in WordPress

There are three Actors in a typical WordPress site (at least the typical ones I create). There is, of course, the Public, who needs to see a well-formatted and clear site, and there is, of course, the Administrator (that is, me), who needs to have an easy way to set up the site and make large changes to it, and there is a third user: the Editor, who is going to be adding the information to the site on a day-to-day basis. The Editor doesn’t have technical skills and should be shown a clean interface where it is obvious how to create and modify rows in the database.

Unfortunately, it is not straightforward to do this in WordPress; this post is a possible path to getting there. Conceptually,  the Administrator would like to create a custom table and specify whatever fields are necessary, then show only those fields to the Editor, who can easily manipulate that table. This example creates a Gigs table, with the fields: Title, Date, End Date, URL, Place, Time, and Price.

First, add the plugin, Custom Post Types UI, and use it to create a Gigs type with Title and Custom Fields checked as the fields. Then add the plugin Advanced Custom Fields and create a Gigs type with the fields you want. Under “Post types” check the gig type.

Then, to get the new columns to show up when adding gigs, add this code to functions.php:

/* Custom Edit Columns */
add_filter("manage_edit-gigs_columns", "gigs_columns");

// rearrange the columns on the Edit screens
function gigs_columns($defaults) {
	// preserve the default date and comment columns
	$date = $defaults['date'];

	// remove default date and comments
	unset($defaults['comments']);
	unset($defaults['date']);

	// insert custom columns
	$defaults['gig_date'] = __('Date');
	$defaults['gig_end_date'] = __('End Date');
	$defaults['url'] = __('URL');
	$defaults['place'] = __('Place');
	$defaults['time'] = __('Time');
	$defaults['price'] = __('Price');

	// restore default date and comments
	$defaults['date'] = $date;

return $defaults;
}

add_action("manage_posts_custom_column", "gigs_custom_column");

// put new columns in admin view
function gigs_custom_column($column) {
	global $post;
	if ($post->post_type == 'gigs') {
		switch ($column) {
		case 'gig_date': echo get_field('date'); break;
		case 'gig_end_date': echo get_field('end_date'); break;
		case 'url': echo get_field('url'); break;
		case 'place': echo get_field('place'); break;
		case 'time': echo get_field('time'); break;
		case 'price': echo get_field('price'); break;
		}
	}
}

Now, when the Editor goes to the Gigs to add one, they will see the fields you created in a way that is easy to update.

But, they won’t show up yet. You need to create a custom page template and associate it with a page. This is slightly different depending on your theme, but here is some code for the Hybrid theme:

<?php 
/* 
Template Name: Custom - Gigs 
*/ 
$this_type = 'gigs'; 
get_header(); ?> 
<div id="content"> 
<?php do_atomic( 'before_content' ); // hybrid_before_content 
?> 
<?php 
global $post; 
$pg = get_page($post->ID); 
setup_postdata($pg); 
echo "<div class='page-content'>"; 
the_content(); 
echo "</div>"; ?> 
<?php 
$orig_query = $wp_query; 
$wp_query = set_custom_query($this_type); 
?> 
<?php 
if ($wp_query->have_posts() ) : while ($wp_query->have_posts() ) : $wp_query->the_post(); ?> 
<div id="post-<?php the_ID(); ?>" 
<?php post_class(); ?>> 
<?php the_custom_post($this_type); ?> 
</div>
<!-- #post-<?php the_ID(); ?> --> 
<?php endwhile; endif; ?> 
<?php wp_reset_query(); 
$wp_query = $orig_query; ?> 
<?php do_atomic( 'after_content' ); // hybrid_after_content ?> 
</div>
<!-- #content --> 
<?php get_footer(); 
?>

I’ve abstracted the parts that are likely to change, so you then need to create the following functions in functions.php:

    function set_custom_query($ty) {
        switch ($ty) {
        case 'gigs':
            $wp_query = new WP_Query();
            $query_args = 'post_type=reviews';
            $wp_query-&gt;query($query_args);
            return $wp_query;
        }
    }

    function format_date($d) {
        if ($d == "")
            return "";
        //$date = DateTime::createFromFormat('Y-m-d', $d);
        //return date_format($date, 'D M d, Y');
        return date("D M d, Y", strtotime($d));
    }

    // Call this inside the loop to output the entire post
    function the_custom_post($ty) {
        switch ($ty) {
        case 'gigs':
            $url = get_field('url');
            if ($url && $url != "")
                the_title( "<div class='entry-title'><a href='" . $url . "' title='" . the_title_attribute( 'echo=0' ) . "' >", "</a></div>" );
            else
                the_title( "<div class='entry-title'>", "</div>" );

            // other meta info
            echo "<div class='gig_details'>";
            echo format_date(get_field('date'));
            $end_date = format_date(get_field('end_date'));
            if ($end_date != "")
                echo " - " . $end_date;
            //echo get_date_from_gmt(get_post_meta(get_the_ID(), "date", true), 'M d, Y');
            echo " ";

            $string = get_field('time');
            if ($string !== "") {
                echo $string;
            }

            echo " ";
            echo get_field('price');
            echo " ";
            echo get_field('place');
            echo "</div>";

            echo '<div>';
            the_excerpt();
            echo '</div>';
            break;
        }
    }

Now, create a page named Gigs, and set its template to “Custom – Gigs” and the gigs that the Editor creates will appear on that page.