Karen Attfield

Happiness Engineer at Automattic

  • Home
  • About
  • Contact

Custom post types & advanced custom fields in Genesis (part 1)

March 29, 2017 by Karen Attfield Leave a Comment

Setting up the custom post type

I recently found myself needing to create a custom post type as well as being able to split the displayed custom posts into two different blocks of pages. This article walks through that process.

In this article I’ll explain how to set up an events custom post type in WordPress as well as adding meta boxes with the advanced custom fields plugin in order to record event dates and to mark the events as current/future or past. We’ll also look at changing the custom post type output within the Genesis Framework (note: affiliate link). With this information we can then split the events into two separate blocks of pages – one for current/future events, and one for past events.

We’ll start by setting up the custom post type. While you could use a plugin such as Custom Post Type UI  we’ll set the custom post type up manually in a plugin. I prefer this method over putting the code in functions.php as the code is then not linked to the theme if you change your sites theme or redesign it, and you can also easily use it elsewhere. Having said that, any custom post types you create still need to be displayed by your theme, so more than likely you will need to do some modifications theme-side (in functions.php or archive template pages) the more complex your output modifications will be.

We’ll also be defining our plugin within a class. This helps with issues created by functions being thrown into the global namespace, and is considered a superior method of defining a plugin. Tom McFarlin has written an in-depth series about implementing object oriented programming in WordPress if you are interested in finding out more.

You create your custom post plugin by creating a file in your plugins folder, and adding a file (for example custom-posts.php) for the plugin code.

Below is the complete plugin code:

<?php
/*Plugin Name: KA Custom Posts
*Description: This plugin registers the 'events' post type.
*Text Domain: ka-custom-posts
*Version: 1.0
*License: GNU General Public License v2 or later
*License URI: http://www.gnu.org/licenses/gpl-2.0.html 
*/


// Exit if accessed directly
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }

    // Check to make sure a class called KA_Custom_Posts doesn't already exist in the global namespace. 
	if ( ! class_exists( 'KA_Custom_Posts' ) ) {

        /**
         * Main Web_Developers_Portfolio class
         */
        // Build the class
        class KA_Custom_Posts {

			// function triggered on initialisation
			public function __construct(){
				add_action( 'init', array($this, 'ka_posts_register'));
			}

			function ka_posts_register() {
					
				// set up labels for Events
				$eventslabels = array(
			 		'name' => 'Events',
			    	'singular_name' => 'Event',
			    	'menu_name' => 'Events',
			    	'new_item' => 'New Event',
			    	'all_items' => 'All Events',
			    	'view_item' => 'View Event',
			    	'search_items' => 'Search Events',
			    	'add_new' => 'Add New Event',
			    	'add_new_item' => 'Add New Event',
			    	'edit_item' => 'Edit Event',
			    	'not_found' =>  'No Events Found',
			    	'not_found_in_trash' => 'No Events found in Trash', 
			    	'ka-custom-posts',
			    );

			    //register post type for Events
				register_post_type( 'event', array(
					'labels' => $eventslabels,
					'has_archive' => true,
			 		'public' => true,
					'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail','page-attributes', 'genesis-seo', 'genesis-cpt-archives-settings'  ),
					'taxonomies' => array( 'post_tag', 'category' ),	
					'exclude_from_search' => false,
					'capability_type' => 'post',
					'rewrite' => array( 'slug' => 'events' ),
					'menu_position' => 20,
					)
				);

			} // end function ka_posts_register
		} // end class KA_Custom_Posts
	} // end beginning if statement


// Check if the class has been defined
if(class_exists('KA_Custom_Posts'))
{
    // instantiate the plugin class
    $wp_plugin_template = new KA_Custom_Posts();
}

I won’t break down the above code as there are many resources on developing custom post types online already. We will look in more detail at integrating the custom fields in order to get the custom event post type to do as we want, as well as modifying the output of the events posts through WordPress actions and filters.

I will however point out the following: if you are using the Genesis Framework you can enable Custom Post Type (CPT) archive settings if you want only a minor level of control over the output, including the ability to add a description to the custom post type page in the same way you would for a normal post (via the Archive Settings link in the WordPress admin dashboard, underneath your custom post type name). You would create an archive template for more complex changes, as described later.

Within your register_post_type() function (and you’ll see this in the code above), you would include support for genesis_cpt_archives-settings, as well as setting several arguments to true:

  •  'has_archive' => true
  •  'public' => true
  •  'show_ui' => true (defaults to true if not added)
  •  'show_in_menu' => true (defaults to true if not added)
  • 'supports' => array( 'title', 'editor', 'genesis-seo', 'thumbnail','genesis-cpt-archives-settings' )

After creating and activating the plugin, you’ll need to reconfigure permalinks in the WordPress dashboard. Make sure post name option is selected. You then create a custom link in your menu – set the address to your-domain.com/events/ (or whatever you have named your custom post type). The posts from that custom post type should then appear on that page, in the same style and format as a normal blog post.

Modifying the output of the custom post type

To modify the output on the front-end, you then create an archive page for the custom post type: archive-events.php. There is no need to copy and paste all the content from archive.php (located in lib/structure under the main genesis theme). Simply add in filters to modify actions to change what is shown on that template page. You can do the same for single archive pages on single-post_type.php. Below is our archive-events.php file with a description of each filter or action (specific to the Genesis Framework) and what it is changing:

<?php
/* 
* Archive Events Template - archive-events.php
*/

//This sets the custom post archive to display the fill content from each post.
add_filter( 'genesis_pre_get_option_content_archive','ka_cp_content_display' );
function ka_cp_content_display() {
 return 'full';
}

//This returns the post thumbnail
add_filter( 'genesis_pre_get_option_content_archive_thumbnail','ka_cp_image_display' );
function ka_cp_image_display() {
 return 1;
}

//Set the image thumbnail size (options: thumbnail, medium, large, and featured-image if defined in your theme)
add_filter( 'genesis_pre_get_option_image_size','ka_cp_image_size' );
function ka_cp_image_size() {
 return 'featured-image';
}

//Changes the image alignment.
add_filter( 'genesis_pre_get_option_image_alignment','ka_cp_image_alignment' );
function ka_cp_image_alignment() {
 return 'aligncenter';
}



// Remove default post title (with link)
remove_action( 'genesis_entry_header','genesis_do_post_title' );


// Function to display the post title without a link
function ka_cp_archive_title() {
	echo '<h2 class="title">' . get_the_title() . '</h2> ';
}

// Add the new post title without a link
add_action( 'genesis_entry_header','ka_cp_archive_title' );


genesis();

We can also modify the output further by removing the entry meta associated with each post (the post author and date). This code needs to go in functions.php, as:

//Remove entry meta for the 'events' post type
function events_remove_entry_meta() {
 	remove_post_type_support( 'events', 'genesis-entry-meta-before-content' );
 	remove_post_type_support( 'events', 'genesis-entry-meta-after-content' );
}
add_action( 'init', 'events_remove_entry_meta', 12 );

In the follow-on article (coming soon) we’ll look at integrating advanced custom fields to our custom post type.

Filed Under: Web development

Dynamic page titles in WordPress using title_tag

December 29, 2016 by Karen Attfield 1 Comment

This article is a follow on from Dynamic page titles in WordPress, where we used wp_title in order to display custom page titles. Since title_tag was introduced in WordPress 4.1, it is now best practice to use this instead of wp_title, which will at some stage be deprecated.

We’ll look at removing wp_title from page titles (through the header’s title tag), and also through dynamically created page titles (for example in h1 / h2 tags on your page).

Adding theme support for title tags

The first step to removing wp_title from the title tag in your WordPress header is by adding theme support in your functions.php file, and then removing the title tag from your header as it is automatically generated. You may also want to add your original custom title code as a fall-back in case the theme you are using does not support title_tag. Here is an example of what the code in your functions.php file should look like:

add_action( 'after_setup_theme', 'yourtheme_setup' );

function yourtheme_setup() {
  add_theme_support( 'title-tag' );
}

/* The below code is a fall-back incase your theme does not support title_tag */
if ( ! function_exists( '_wp_render_title_tag' ) ) :

   function yourtheme_render_title() {
   ?>

   <title>
   // add the original code between your title tags here
   </title>
   <?php
   }
   add_action( 'wp_head', 'yourtheme_render_title' );

endif;

The result you will see will depend on other plugins you are using that also modify the title tag, for example the Yoast SEO plugin. I’ll look at a solution both without plugins, and with Yoast SEO activated.

Customising dynamic titles without Yoast SEO installed

With Yoast SEO not activated, we need to create a custom function (custom_theme_titles) in functions.php. In it, we need to modify the title output by modifying document_title_parts through a filter. In the below example I am modifying the ‘title’ and ‘site’, both parameters within document_title_parts. In order to get the information I need, I am using get_bloginfo() to retrieve the site description and name. In the case of category pages I’m using get_the_category() to retrieve the relevant category, and then pulling out the name as a string with cat_name. I’ve unset $titleparts[‘site’] as leaving it set added my site title to the end of the title, which I didn’t want.

The result of the below code is a page title of ‘Page Name | Sitename – Tagline’ (and just ‘Sitename – Tagline’ on the front-page) that dynamically fills the title tag on every page (including a custom 404 page title, and custom category page titles).

function custom_theme_titles( $titleparts ) {
   if ( is_front_page() ) {
    	$pagetitle = $titleparts['title'];  
        $titleparts['title'] = $pagetitle;
        unset( $titleparts['site'] );
    }
    elseif ( is_404() ) {
    	$pagetitle = "404";
    	$sep = " | ";
        $name = get_bloginfo( 'name', 'display' );
        $sep2 = " - ";
        $desc = get_bloginfo( 'description', 'display' );
        $titleparts['title'] = $pagetitle.$sep.$name.$sep2.$desc;
        unset( $titleparts['site'] );
    }
    elseif (is_category() ) {	
		$category = get_the_category();
		$catName = $category[0]->cat_name;		
		$pagetitle = "Blog - ".$catName." archives";		
    	$sep = " | ";
        $name = get_bloginfo( 'name', 'display' );
        $sep2 = " - ";
        $desc = get_bloginfo( 'description', 'display' );
        $titleparts['title'] = $pagetitle.$sep.$name.$sep2.$desc;
        unset( $titleparts['site'] );
    }   
    else {
  		$pagetitle = $titleparts['title'];
        $sep = " | ";
        $name = get_bloginfo( 'name', 'display' );
        $sep2 = " - ";
        $desc = get_bloginfo( 'description', 'display' );
        $titleparts['title'] = $pagetitle.$sep.$name.$sep2.$desc;
        unset( $titleparts['site'] );   
    }

    return $titleparts;
}
add_filter( 'document_title_parts', 'custom_theme_titles', PHP_INT_MAX );

Customising dynamic titles with Yoast SEO installed

The code snippet to modify titles when Yoast SEO is installed seems a lot simpler, as they have their own filter for the title – wpseo_title. The first step is to define a function that is later passed through the wpseo_filter. First, we set a few variables – a separator, the site name and the site tagline/description. We can then modify the output for different pages, for example returning just the page title (in the default format of ‘Sitename – Tagline’) on the front page (not adding this may result in a duplicate title), custom page title format throughout the site, and also custom individual pages such as a 404 page.

function custom_theme_titles_yoast( $title ) {
    $sep = '|';
    $name = get_bloginfo( 'name' );
    $desc = get_bloginfo( 'description', 'display' );

    if( is_front_page() ) {
        $pagetitle = $title;
        return "{$pagetitle}";
    }
     elseif( is_404() ) {
        $pagetitle = "404";
        return "{$pagetitle} {$sep} {$name} - {$desc}"; 
    }
    else {
        $pagetitle = $title;   
        return "{$pagetitle} {$sep} {$name} - {$desc}";
    }
}
add_filter( 'wpseo_title', 'custom_theme_titles_yoast', PHP_INT_MAX );

If you change the SEO title on any individual page through the Yoast SEO box in the page/post editor, this will alter the title in the title tag for that page (specifically, it will only alter the $title variable in the above code snippet).

Custom on-page titles

Displaying page titles on pages is not too dissimilar to the process shown in the previous article on dynamic page titles, but with a slight change for the wp_title() calls, to use get_the_title() instead. Get_the_title doesn’t work for archive pages as by default it pulls the title of the first post as the page title, so you’ll need separate if statements to cover any archive pages you might use. This code would then go within your header.php file, or wherever you are dynamically adding on-page titles.

<div class="page-title">
			
   <h1> 
	<?php
	if (is_search()) {
		echo "Blog";
	}
	elseif (is_404()) {
		echo "404";
	}
	elseif (is_category()) {
		$category = get_the_category();
		$catName = $category[0]->cat_name;
		$archive_name = "- ".$catName." archives";
		echo "Blog ".$archive_name;
	}
	else {
		echo get_the_title();
	} 
	?>
			 	
   </h1>

</div>

The result should be clean, custom dynamic page titles on your WordPress site, regardless of whether you have Yoast SEO activated or not.

Filed Under: Web development

Dynamic page titles in WordPress

December 19, 2016 by Karen Attfield 1 Comment

If you are developing a custom theme in WordPress and want custom page titles to display in your header or at the top of the page using the wp_title filter, you will have noticed that WordPress by default adds the site title to the page title. If you have the Yoast SEO plugin installed, you may have noticed that the site title is appended to your custom page titles regardless of what you have put in the wp_title filter. Let’s look at the wp_title filter first for both title tags and on-page titles, and then we’ll take a look at how to change the Yoast SEO settings to show your custom title.

As outlined on WordPress.org, wp_title takes the following parameters:

wp_title( string $sep = '»', bool $display = true, string $seplocation = '' )

So to remove the site description and the separator, we would write:

wp_title('', true)

The first parameter removes the separator, true allows the page title to show, and we don’t need to specify whether the page title is to the left or right of the site title as we only want to output the page title.

Customising dynamic titles

This works great, until we want custom page titles for custom page templates. Within the head tag in our header we’d need to add a title tag with conditionals for specific pages. The get_bloginfo() function allows us to pull the information we need (site description or name in this case) and place it in the order we want to show it, along with any custom text.

<title>
            <?php
		    if (is_front_page() ) {
				echo get_bloginfo( 'name' );
				?>
				-
				<?php
				echo get_bloginfo( 'description' );
		}
		
			elseif (is_404()) {
				echo "404";
				?>
				|
				<?php
				echo get_bloginfo( 'name' );
				?>
				-
				<?php
				echo get_bloginfo( 'description' );
			}
			
			else {
                wp_title('|', true, 'right'); ?> 
                | 
                <?php 
                echo get_bloginfo( 'name' ); 
                ?>
                - 
                <?php 
                echo get_bloginfo( 'description' ); 
             } 
             ?> 
</title>

Customising dynamic titles on-page

Within your header.php file or whichever file you are planning on adding custom, dynamic on-page titles, you again need some custom code for the different page templates. For example, let’s say you’ve added a 404.php template. You’ll now most likely have a generic title added to your site title, to create one long title. Not great. A solution is to echo the page name if the page is a custom template, within your page title h tag:

<div class="page-title">
			
	<h1> 
		<?php
                if (is_404()) {
                   echo "404"; // or any title of your choice
                }
                else {
                   wp_title('', true);
                }
                ?>
	</h1>
</div>

You may have then found that if you install Yoast SEO, the site title gets added back on to the page title, or a different title takes its place. To change this, navigate to the Yoast SEO dashboard in your WordPress dashboard and click on the features tab in the top menu. Make sure ‘advanced settings pages’ is enabled. This will add new menu items in the SEO navigation menu on the left of your WordPress dashboard. From these new options, open up the ‘Titles and Metas’ section and make sure ‘Force rewrite titles’ is disabled from the ‘General’ tab.

Yoast Dashboard Features

Navigate to the ‘Post Types’ tab, and in here you need to change the title template for posts, pages and media if relevant. I found that the default title template for posts was %%sep%% %%sitename%%, and the result was a title on my blog pages showing just the separator and my site name. I found that deleting the content in this box wasn’t enough to return the title back to my custom title (showing just the article name), but by adding %%title%% to this box the title showed as expected.

Yoast Dashboard Titles Metas

If you find that removing the text inputted automatically by Yoast SEO does not change the page title, then you can follow their coding styles to recreate your custom page/post titles. Yoast SEO have compiled a list of all the variables that can be used in the Titles and Meta section of their dashboard.

Yoast SEO will allow you to set custom title templates for category pages, tag pages, archive pages, and ‘special’ pages (which only includes 404 pages and search pages).

Note: If you have added support in your theme for the new title_tag (which you will need to do if you intend to distribute your themes in the WordPress theme repository), you won’t be able to use wp_title within the theme. It will also be deprecated at some stage in the future, but is currently still included. Find out how to create custom page titles with the title_tag in the next article.

Filed Under: Web development

  • « Previous Page
  • 1
  • 2

Copyright © 2021 · Easeful