Andreas Hecht September 19th, 2017

The 26 Most Useful and Most Functional WordPress Snippets

WordPress becomes better with the plugins, as they allow you to fully customize your website to fulfill your needs. However, many functions can also be integrated without using a plugin. A simple snippet does the trick. Collecting all the required snippets can be pretty tedious, though. Thus, today, I'll open my toolbox and list my favorite WordPress snippets for you. Compatibility:
  • WordPress Version up from 4.6
  • PHP-Version 7.xx
Either copy the snippets into your active theme's functions.php, or set up a page-specific custom plugin for this job. [Red-Box text="Remember: Before you apply any changes to the functions.php, create a backup of the file. Don't alter the file using the WordPress editor. If something goes wrong, you won't have access to your website. Make your additions using an FTP access, directly on your web space."] The WordPress Tag Cloud is a popular tool for a blog's sidebar. Your visitors can use it to easily find what they're looking for. However, WordPress displays the tags in different sizes, which is not always a desired thing. Use this snippet to remove the inline styles.
<?php

/**
 * Remove style from Tag Clouds
 * @author Andreas Hecht
 */
function drweb_remove_tagcloud_inline_style($input){ 
    return preg_replace('/ style=("|\')(.*?)("|\')/','',$input); 
}
add_filter('wp_generate_tag_cloud', 'drweb_remove_tagcloud_inline_style',10,1); 

2 - Turn Off Your Self-referring Pingbacks

Pingbacks and trackbacks are not generally bad. They tell you if your articles were mentioned or linked on other websites. Sadly, WordPress has the bad habit of informing you about links of your articles on your own website. This snippet lets you turn off these annoying messages.
<?php

/**
 * Disable self pingbacks
 * 
 */
function evolution_no_self_ping( &$links ) {
    $home = get_option( 'home' );
    foreach ( $links as $l => $link )
        if ( 0 === strpos( $link, $home ) )
            unset($links[$l]);
}

add_action( 'pre_ping', 'evolution_no_self_ping' );

3 - Turn Off WordPress Emojis

Not everyone is a fan of the colorful emojis. If you don't want to use emojis in your posts, you can deactivate this feature. Your blog's performance will thank you.
<?php

/**
* Disable the emojis
*/
function disable_emojis() {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' ); 
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' ); 
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
    add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
    add_filter( 'wp_resource_hints', 'disable_emojis_remove_dns_prefetch', 10, 2 );
}
add_action( 'init', 'disable_emojis' );

/**
* Filter function used to remove the tinymce emoji plugin.
* 
* @param array $plugins 
* @return array Difference betwen the two arrays
*/
function disable_emojis_tinymce( $plugins ) {
    if ( is_array( $plugins ) ) {
        return array_diff( $plugins, array( 'wpemoji' ) );
    } else {
        return array();
    }
}

/**
* Remove emoji CDN hostname from DNS prefetching hints.
*
* @param array $urls URLs to print for resource hints.
* @param string $relation_type The relation type the URLs are printed for.
* @return array Difference betwen the two arrays.
*/
function disable_emojis_remove_dns_prefetch( $urls, $relation_type ) {
    if ( 'dns-prefetch' == $relation_type ) {
        /** This filter is documented in wp-includes/formatting.php */
        $emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/' );

        $urls = array_diff( $urls, array( $emoji_svg_url ) );
    }

    return $urls;
}

4 - Turn Off the jQuery Migrate Script

jQuery Migrate is a script meant to create a downward compatibility of older jQuery applications. The "normal" and modern jQuery version does not support all old applications anymore. While this won't affect more than 5% of all WordPress website, WordPress loads the pretty sizeable script by default. Here's an easy way to turn it off:
<?php

/**
* Dequeue jQuery Migrate Script in WordPress.
*/
if ( ! function_exists( 'evolution_remove_jquery_migrate' ) ) :

function evolution_remove_jquery_migrate( &$scripts) {
    if(!is_admin()) {
        $scripts->remove( 'jquery');
        $scripts->add( 'jquery', false, array( 'jquery-core' ), '1.12.4' );
    }
}
add_filter( 'wp_default_scripts', 'evolution_remove_jquery_migrate' );
endif;

5 - Deactivate the WordPress oEmbed Function

The WordPress version 4.4 brought us the new function oEmbed, which is mainly meant to allow you to integrate foreign articles or pages into your posts with a simple link. If you don't need this function, or you simply don't want your articles to be able to be displayed in foreign posts at any time, just deactivate this function.
<?php
/**
 * Disable embeds on init.
 *
 * - Removes the needed query vars.
 * - Disables oEmbed discovery.
 * - Completely removes the related JavaScript.
 *
 * @since 1.0.0
 */
function evolution_disable_embeds_init() {
    /* @var WP $wp */
    global $wp;

    // Remove the embed query var.
    $wp->public_query_vars = array_diff( $wp->public_query_vars, array(
        'embed',
    ) );

    // Remove the REST API endpoint.
    remove_action( 'rest_api_init', 'wp_oembed_register_route' );

    // Turn off oEmbed auto discovery.
    add_filter( 'embed_oembed_discover', '__return_false' );

    // Don't filter oEmbed results.
    remove_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10 );

    // Remove oEmbed discovery links.
    remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );

    // Remove oEmbed-specific JavaScript from the front-end and back-end.
    remove_action( 'wp_head', 'wp_oembed_add_host_js' );
    add_filter( 'tiny_mce_plugins', 'evolution_disable_embeds_tiny_mce_plugin' );

    // Remove all embeds rewrite rules.
    add_filter( 'rewrite_rules_array', 'disable_embeds_rewrites' );

    // Remove filter of the oEmbed result before any HTTP requests are made.
    remove_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10 );
}

add_action( 'init', 'evolution_disable_embeds_init', 9999 );

/**
 * Removes the 'wpembed' TinyMCE plugin.
 *
 * @since 1.0.0
 *
 * @param array $plugins List of TinyMCE plugins.
 * @return array The modified list.
 */
function evolution_disable_embeds_tiny_mce_plugin( $plugins ) {
    return array_diff( $plugins, array( 'wpembed' ) );
}

/**
 * Remove all rewrite rules related to embeds.
 *
 * @since 1.0.0
 *
 * @param array $rules WordPress rewrite rules.
 * @return array Rewrite rules without embeds rules.
 */
function evolution_disable_embeds_rewrites( $rules ) {
    foreach ( $rules as $rule => $rewrite ) {
        if ( false !== strpos( $rewrite, 'embed=true' ) ) {
            unset( $rules[ $rule ] );
        }
    }

    return $rules;
}

/**
 * Remove embeds rewrite rules on plugin activation.
 *
 * @since 1.0.0
 */
function evolution_disable_embeds_remove_rewrite_rules() {
    add_filter( 'rewrite_rules_array', 'disable_embeds_rewrites' );
    flush_rewrite_rules( false );
}

register_activation_hook( __FILE__, 'evolution_disable_embeds_remove_rewrite_rules' );

/**
 * Flush rewrite rules on plugin deactivation.
 *
 * @since 1.0.0
 */
function evolution_disable_embeds_flush_rewrite_rules() {
    remove_filter( 'rewrite_rules_array', 'disable_embeds_rewrites' );
    flush_rewrite_rules( false );
}

register_deactivation_hook( __FILE__, 'evolution_disable_embeds_flush_rewrite_rules' );

6 - Free the WordPress Header From Unnecessary Entries

WordPress loads a bunch of things via the wp_head() hook into the header of the WordPress themes. Some of them are very useful, some aren't. Some just inflate the website unnecessarily. Here's a small snippet to do some major cleaning up.
<?php

/**
 * Frees the header from unnecessary entries
 */ 
add_action('init', 'evolution_remheadlink');
function evolution_remheadlink()
{
    remove_action('wp_head', 'rsd_link');
    remove_action('wp_head', 'wp_generator');
    remove_action('wp_head', 'index_rel_link');
    remove_action('wp_head', 'wlwmanifest_link');
    remove_action('wp_head', 'feed_links', 2);
    remove_action('wp_head', 'feed_links_extra', 3);
    remove_action('wp_head', 'parent_post_rel_link', 10, 0);
    remove_action('wp_head', 'start_post_rel_link', 10, 0);
    remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0);
    remove_action('wp_head', 'wp_shortlink_header', 10, 0);
    remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
}

7 - Inject Post Images Into the RSS Feed

By default, WordPress doesn't add post images to the RSS feed. This snippet changes that.
<?php

/**
 * Add Post Images to the RSS Feed 
 */
function evolution_featuredtoRSS($content) {
global $post;
if ( has_post_thumbnail( $post->ID ) ){
$content = '<div>' . get_the_post_thumbnail( $post->ID, 'large', array( 'style' => 'margin-bottom: 15px;' ) ) . '</div>' . $content;
}
return $content;
}
 
add_filter('the_excerpt_rss', 'evolution_featuredtoRSS');
add_filter('the_content_feed', 'evolution_featuredtoRSS');

8 - Allow Additional File Formats For the Media Library

You want to upload special file formats to your WordPress media library, and you get an error message? Use this code, and your problem is solved. The code allows you to upload the file formats ZIPMOBIPDF, and EPUB. If you happen to need more formats, find the complete list of MIME types here.
<?php

/**
 * Add further Mime types for the download of the products 
 */
function add_custom_mime_types($mimes){

 $new_file_types = array (
 'zip' => 'application/zip',
 'mobi' => 'application/x-mobipocket-ebook',
 'pdf' => 'application/pdf',
 'epub' => 'application/epub+zip'
 );

 return array_merge($mimes,$new_file_types);
}
add_filter('upload_mimes','add_custom_mime_types');

9 - Freely Define the Length of the Excerpt

Sometimes, a very precise excerpt length is needed for a certain template. The following function lets you define this length freely. The good thing is that the excerpt length is not set globally, allowing each template to have its own length.
<?php

/**
 * Custom Excerpt Lenght
 * 
 */ 
the_excerpt_max_charlength(190);

function the_excerpt_max_charlength($charlength) {
	$excerpt = get_the_excerpt();
	$charlength++;

	if ( mb_strlen( $excerpt ) > $charlength ) {
		$subex = mb_substr( $excerpt, 0, $charlength - 5 );
		$exwords = explode( ' ', $subex );
		$excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
		if ( $excut < 0 ) {
			echo mb_substr( $subex, 0, $excut );
		} else {
			echo $subex;
		}
		echo '...';
	} else {
		echo $excerpt;
	}
}
In the template, just exchange the tags and define the excerpt length:
// Deleting the original tag:
<?php the_excerpt(); ?>

// Exchange with this tag, and enter any length (in brackets):
<?php the_excerpt_max_charlength( 250 ); ?>

10 - Responsive Videos - YouTube and Vimeo

If your theme doesn't support responsive videos, setting up the support to do so can be done very quickly. A PHP function makes for an automatic embedding in a Div, while the CSS information makes sure there's an optimal scaling at any resolution.
<?php

/**
 * Responsive Videos, Youtube and Vimeo
 * 
 */
function evolution_wrap_oembed( $html ){
    $html = preg_replace( '/(width|height)="\d*"\s/', "", $html ); // Strip width and height #1

    return'<div class="embed-responsive embed-responsive-16by9">'.$html.'</div>'; // Wrap in div element and return #3 and #4

}
add_filter( 'embed_oembed_html','evolution_wrap_oembed',10,1);
The necessary CSS:
.embed-responsive.embed-responsive-16by9 {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 */
    padding-top: 25px;
    height: 0;
}
.embed-responsive.embed-responsive-16by9 iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
/* This indication makes HTML5 videos responsive */
video {
    width: 100% !important;
    height: auto !important;
}

11 - Setting Up WordPress Pagination Without a Plugin

Do you want to replace the "older posts | newer posts" with a cool list of numbers? No problem, as with WordPress version 4.1 you don't need the popular plugin WP PageNavi anymore. Now, doing this is very easy to do using default means. You can use this function directly within the index.php , and in the archive.php. However, creating a child theme to do so is advantageous.
<?php the_posts_pagination( array(
 'mid_size' => 3, //How many buttons will be displayed before the placeholder »...« appears.
 'type' => 'list', // Display as a list 
 'prev_text' => __( '« Newer', 'textdomain' ),
 'next_text' => __( 'Older »', 'textdomain' ),
 ) ); ?>
To give the list a design, some CSS is needed. Here are the styles that I use every now and then. You need to adjust it to your blog colors:
nav.pagination{position:relative;display:block;margin-top:20px}
.page-numbers{margin:0;padding:0}
.page-numbers li{list-style:none;margin:0 6px 0 0;padding:0;display:inline-block}
.page-numbers li span.current{padding:10px 15px;background:#9FC65D;border:1px solid #9FC65D;display:block;line-height:1;color:#fff}
.page-numbers li a{padding:10px 15px;background:#eee;color:#555;text-decoration:none;border:1px solid #eee;display:block;line-height:1}
.page-numbers li a:hover{background:#9FC65D;border-color:#9FC65D;color:#fff}
.screen-reader-text {
 clip: rect(1px,1px,1px,1px);
 position: absolute!important;
 height: 1px;
 width: 1px;
 overflow: hidden;
}

12 - Custom Login Logo With a Custom Background Color

You are really proud of your WordPress website, and you put lots of effort into the design? Take it a step further, and adjust the logo on the login page. In combination with your own background color, this looks really nice.
<?php

/**
 * A new logo for the admin area and an own background color 
 * @author Andreas Hecht
 */
function ah_login_logo() { 
?>
 <style type="text/css">
 #login h1 a, .login h1 a {
 background-image: url(<?php echo get_stylesheet_directory_uri(); ?>/images/dein-logo.png);
 margin-bottom: 0;
 background-size: 180px;
 height: 180px;
 width: 180px;
 margin-left: auto;
 margin-right: auto;
 border-radius: 50%;
 }
 body.login {background-color: #0073bf;} .login #backtoblog a, .login #nav a {color: #fff !important}
 </style>
<?php }
add_action( 'login_enqueue_scripts', 'ah_login_logo' );

13 - Change the Look of the First Paragraph

Your article will only look really cool when the first paragraph is designed in a different color and font. To do so, you don't even need to switch into the text area of your editor, as WordPress itself can do that for you automatically. Two snippets do the trick:
<?php

/**
 * Auto-Highlighting - Automatic highlighting of a post's first paragraph 
 * @author Andreas Hecht
 */
function tb_first_paragraph_highlight( $content ) {
    return preg_replace( '/<p([^>]+)?>/', '<p$1 class="opener">', $content, 1 );
}
add_filter( 'the_content', 'tb_first_paragraph_highlight' );
The code above adds the class .opener to every article's or page's first paragraph. Now, a bit of CSS lets you control the paragraph's formatting, as well as the "place" of action.
/* Only selected articles get the design */
.single p.opener {
    color: #165a72;
    font-weight: 400;
    font-size: 21px;
    line-height: 1.5;
}
Or articles and pages display the first paragraph differently:
/* Individual articles and pages are designed */
.single p.opener, .page p.opener {
    color: #165a72;
    font-weight: 400;
    font-size: 21px;
    line-height: 1.5;
}

14 - User Signup With Email and Password Only

Since WordPress version 4.5, a user signup via email address and password is possible. In order to annoy hackers, and make WordPress a bit safer, you can sign up via email and password exclusively using this code.
<?php

// Copy from here
//Deleting WordPress authentification
remove_filter('authenticate', 'wp_authenticate_username_password', 20);

// Placing new authentification - sign up via email and password only
add_filter('authenticate', function($user, $email, $password){
 
    //Check for empty fields
        if(empty($email) || empty ($password)){        
            //create new error object and add errors to it.
            $error = new WP_Error();
 
            if(empty($email)){ //No email
                $error->add('empty_username', __('<strong>ERROR</strong>: Email field is empty.'));
            }
            else if(!filter_var($email, FILTER_VALIDATE_EMAIL)){ //Invalid Email
                $error->add('invalid_username', __('<strong>ERROR</strong>: Email is invalid.'));
            }
 
            if(empty($password)){ //No password
                $error->add('empty_password', __('<strong>ERROR</strong>: Password field is empty.'));
            }
 
            return $error;
        }
 
        //Check if user exists in WordPress database
        $user = get_user_by('email', $email);
 
        //bad email
        if(!$user){
            $error = new WP_Error();
            $error->add('invalid', __('<strong>ERROR</strong>: Either the email or password you entered is invalid.'));
            return $error;
        }
        else{ //check password
            if(!wp_check_password($password, $user->user_pass, $user->ID)){ //bad password
                $error = new WP_Error();
                $error->add('invalid', __('<strong>ERROR</strong>: Either the email or password you entered is invalid.'));
                return $error;
            }else{
                return $user; //passed
            }
        }
}, 20, 3);

15 - Prevent Users From Changing Their Passwords

The WordPress admin area is the heart and the lungs of your website. Make sure that the distributed passwords are very safe, giving attackers no chance. Users like to change the assigned passwords into very easy to remember, and very easy to hack versions, though. You can prevent that!
<?php

/**
 *
 * Preventing users from changing their passwords 
 * 
 */ 
class Password_Reset_Removed
{

  function __construct() 
  {
    add_filter( 'show_password_fields', array( $this, 'disable' ) );
    add_filter( 'allow_password_reset', array( $this, 'disable' ) );
  }

  function disable() 
  {
    if ( is_admin() ) {
      $userdata = wp_get_current_user();
      $user = new WP_User($userdata->ID);
      if ( !empty( $user->roles ) && is_array( $user->roles ) && $user->roles[0] == 'administrator' )
        return true;
    }
    return false;
  }

}

$pass_reset_removed = new Password_Reset_Removed();

16 - Displaying Ads After the xx Paragraph

If you want to make money off your blog, you won't get around using ads. You could use the popular Google Adsense, for example. This snippet displays your ads after a selected paragraph.
<?php
/**
 * Adding an ad after the second paragraph
 * 
 */ 
add_filter( 'the_content', 'tb_insert_post_ads' );

function tb_insert_post_ads( $content ) {
	
	$ad_code = 'The ad code goes here. Both static ads and Google Adsense.';

	if ( is_single() && ! is_admin() ) {
        // The number in front of the content defines where the code appears. Here, it pops up after the article's second paragraph.
		return tb_insert_after_paragraph( $ad_code, 2, $content );
	}
	
	return $content;
}
 
// Parent Function that makes the magic happen
 
function tb_insert_after_paragraph( $insertion, $paragraph_id, $content ) {
	$closing_p = '</p>';
	$paragraphs = explode( $closing_p, $content );
	foreach ($paragraphs as $index => $paragraph) {

		if ( trim( $paragraph ) ) {
			$paragraphs[$index] .= $closing_p;
		}

		if ( $paragraph_id == $index + 1 ) {
			$paragraphs[$index] .= $insertion;
		}
	}
	
	return implode( '', $paragraphs );
}

17 - Expanding Your User Profile With Further Social Media Accounts

The biographic information in your WordPress profile is pretty thin. You don't have the option to link all of your social networks. With this code, you can add and display all of your social media accounts.
<?php

/**
 * Managing contact fields for author bio
 */
$evolution_pro_Contactfields = new evolution_pro_Contactfields(
// Missing accounts can easily be added 
       array (
	'Feed',
	'Twitter',
        'Facebook',
        'GooglePlus',
        'Flickr',
        'Xing',
        'Github',
        'Instagram',
        'LinkedIn',
        'Pinterest',
        'Vimeo',
        'Youtube'
	)
);

class evolution_pro_Contactfields {
	public
		$new_fields
	,	$active_fields
	,	$replace
	;

	/**
	 * @param array $fields New fields: array ('Twitter', 'Facebook')
	 * @param bool $replace Replace default fields?
	 */
	public function __construct($fields, $replace = TRUE)
	{
		foreach ( $fields as $field )
		{
			$this->new_fields[ mb_strtolower($field, 'utf-8') ] = $field;
		}

		$this->replace = (bool) $replace;

		add_filter('user_contactmethods', array( $this, 'add_fields' ) );
	}

	/**
	 * Changing contact fields
	 * @param  $original_fields Original WP fields
	 * @return array
	 */
	public function add_fields($original_fields)
	{
		if ( $this->replace )
		{
			$this->active_fields = $this->new_fields;
			return $this->new_fields;
		}

		$this->active_fields = array_merge($original_fields, $this->new_fields);
		return $this->active_fields;
	}

	/**
	 * Helper function
	 * @return array The currently active fields.
	 */
	public function get_active_fields()
	{
		return $this->active_fields;
	}
}
Use the following tag to display the new fields in the theme:
<?php echo get_the_author_meta( 'facebook' ); ?>

18 - Display a Category List With RSS Feeds

Sometimes, being able to display all categories with their respective RSS feed addresses can be handy. It gets even better when you are able to use a WordPress shortcode to display the list anywhere - even in the text widgets.
<?php

function tb_categories_with_feed() { 
	$args = array(
		'orderby' => 'name',
		'feed' => 'RSS', 
		'echo' => false, 
		'title_li'     => '',
	); 
	$string .= '<ul>';
	$string .= wp_list_categories($args); 
	$string .= '</ul>'; 

	return $string; 

}

// add shortcode
add_shortcode('categories-feed', 'tb_categories_with_feed'); 

// Add filter to execute shortcodes in text widgets
add_filter('widget_text', 'do_shortcode');
The Shortcode: [categories-feed] lets you display the list wherever you want to. It also works within widgets. You can also use the shortcode in your theme:
<?php echo do_shortcode("[categories-feed]"); ?>

19 - Display Related Posts Without a Plugin

The popular similar posts can easily be displayed without an inflated plugin with "many" functions. You need a PHP snippet, a child theme, and a bit of CSS.
<?php

if ( ! function_exists( 'evolution_related_posts' ) ) :

function evolution_related_posts() {
    
global $post;
    
if($post) {
 $post_id = get_the_ID();
} else {
 $post_id = null;
}
$orig_post = $post;    
$categories = get_the_category($post->ID);
if ($categories) {
$category_ids = array();
foreach($categories as $individual_category) $category_ids[] = $individual_category->term_id;
$args=array(
'category__in' => $category_ids,
'post__not_in' => array($post->ID),
'posts_per_page'=> 3, // Number of related posts that will be shown.
'ignore_sticky_posts'=>1
);
$my_query = new wp_query( $args );
if( $my_query->have_posts() )  { 
echo '<div class="related-wrap">';    
echo '<h4 class="entry-related">';
_e('Related Posts','evolution');   
echo '</h4>';
echo '<div class="related-posts">';    
$c = 0; while( $my_query->have_posts() ) {
$my_query->the_post(); $c++; 
if( $c == 3) {
	$style = 'third';
	$c = 0;
}
else $style=''; ?>
<article class="entry-item <?php echo $style; ?>">                                         
<div class="entry-thumb">                                                  
<a href="<?php the_permalink($post->ID); ?>" title="<?php the_title(); ?>"><?php the_post_thumbnail( 'evolution-medium' ); ?></a>                            
    </div>                                          
<div class="content">
<?php if ( ! empty( $categories ) ) {
    echo '<span class="cat"><i class="icon-folder-open" aria-hidden="true"></i> <a href="' . esc_url( get_category_link( $categories[0]->term_id ) ) . '">' . esc_html( $categories[0]->name ) . '</a></span>';
} ?>
<header>
<h4 class="entry-title"><a href="<?php the_permalink($post->ID); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h4>
</header>
</div><!-- content -->
</article><!-- entry-item -->
<?php
}
echo '</div></div>';
echo '<div class="clear"></div>';    
}
}
$post = $orig_post;
wp_reset_postdata();    
}
endif;
After the code has been copied to the functions.php, a tag had to be added in the single.php, or the template that contains the loop of individual posts.
<?php evolution_related_posts(); ?>
To make sure that the whole thing looks nice, some CSS is required:
.related-posts {
    display: flex;
}
.related-posts .entry-title {
    font-size: 1rem;
}
.related-posts .cat {
    color: #ba9e30;
    font-size: 0.85rem;
}
.related-posts .entry-item {
    width: 31%;
    margin-right: 3.5%;
    position: relative;
    float: left;
}
.related-posts .entry-item.third {
    margin-right: 0;
}
.related-posts a img:hover {
    opacity: .85;
}
.entry-related {
    padding-bottom: 10px;
    border-bottom: 1px solid #ddd;
    margin-bottom: 20px
}
.related-wrap {
    margin-bottom: 70px;
}

20 - Creating a Sitemap.XML Without a Plugin

In combination with the Google Search Console (formerly Webmaster Tools), the sitemap.xml makes for a fast indexation of your website's posts. Previously, you had to install a plugin in order to generate a sitemap.xml. With this code, you can forgo the plugin. [blue-box text="The sitemap is created for your posts, the pages, and the images in the media library."]
<?php

// Copy from here
/**
 * Creating an own sitemap.xml without a plugin
 * @author Andreas Hecht
 */
function ah_create_sitemap() {
  $sitemap_posts = get_posts(array(
    'numberposts' => -1,
    'orderby' => 'modified',
    'post_type'  => array('post','page', 'attachment'), // Deine Custom Post Types hier einfügen (z.B. Portfolio)
    'order'    => 'DESC'
  ));

  $sitemap = '<?xml version="1.0" encoding="UTF-8"?>';
  $sitemap .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

  foreach($sitemap_posts as $post) {
    setup_postdata($post);

    $postdate = explode(" ", $post->post_modified);

  	$sitemap .= '<url>'.
      '<loc>'. get_permalink($post->ID) .'</loc>'.
      '<lastmod>'. $postdate[0] .'</lastmod>'.
      '<changefreq>monthly</changefreq>'.
    '</url>';
  }
  $sitemap .= '</urlset>';

  $fp = fopen(ABSPATH . "sitemap.xml", 'w');
  fwrite($fp, $sitemap);
  fclose($fp);
}
add_action('publish_post', 'ah_create_sitemap');
add_action('publish_page', 'ah_create_sitemap');

21 - Make Post Images Mandatory

The following snippet could be very useful for blogs with multiple authors, as it makes post images required in order to be able to publish an article.
<?php

add_action('save_post', 'evolution_check_thumbnail');
add_action('admin_notices', 'evolution_thumbnail_error');

function evolution_check_thumbnail($post_id) {
    // change to any custom post type
    if(get_post_type($post_id) != 'post')
        return;
    if ( !has_post_thumbnail( $post_id ) ) {
        // set a transient to show the users an admin message
        set_transient( "has_post_thumbnail", "no" );
        // unhook this function so it doesn't loop infinitely
        remove_action('save_post', 'evolution_check_thumbnail');
        // update the post set it to draft
        wp_update_post(array('ID' => $post_id, 'post_status' => 'draft'));
        add_action('save_post', 'evolution_check_thumbnail');
    } else {
        delete_transient( "has_post_thumbnail" );
    }
}
function evolution_thumbnail_error()
{
    // check if the transient is set, and display the error message
    if ( get_transient( "has_post_thumbnail" ) == "no" ) {
        echo "<div id='message' class='error'><p><strong>You have to assign a post image. Without a post image, the article can't be published.</strong></p></div>";
        delete_transient( "has_post_thumbnail" );
    }
}

22 - Automatically Link Twitter Accounts

If you tend to link Twitter accounts in your posts, you'll love this snippet. When entering @account, it will automatically link the according Twitter account.
<?php

function content_twitter_mention($content) {
	return preg_replace('/([^a-zA-Z0-9-_&])@([0-9a-zA-Z_]+)/', "$1<a href=\"http://twitter.com/$2\" target=\"_blank\" rel=\"nofollow\">@$2</a>", $content);
}

add_filter('the_content', 'content_twitter_mention');   
add_filter('comment_text', 'content_twitter_mention');

23 - Prevent Automatic Linking in User Comments

Every URL entered in the comments is automatically turned into a link by WordPress. This can become a problem, as not all of those links are worth being linked on your blog. The following snippet turns the URLs into pure text.
<?php

remove_filter('comment_text', 'make_clickable', 9);

24 - Load the Entire JavaScript in the Footer

WordPress normally loads the JavaScript into the header of your website. This slows down the page buildup by a lot. With this code, the entire JavaScript is loaded in the footer, allowing the site to build up faster.
<?php

/**
 * @uses wp_head() and wp_enqueue_scripts()
 * 
 */
if ( !function_exists( 'evolution_footer_scripts' ) ) {
    
    function evolution_footer_scripts() { 

	   remove_action('wp_head', 'wp_print_scripts'); 
	   remove_action('wp_head', 'wp_print_head_scripts', 9); 
	   remove_action('wp_head', 'wp_enqueue_scripts', 1); 
    } 
}
add_action( 'wp_enqueue_scripts', 'evolution_footer_scripts' );

25 - Create a Breadcrumb Navigation Without a Plugin

You don't need an overloaded plugin for a breadcrumb navigation. A few lines of code are all it takes.
<?php
// Copy from here

function ah_the_breadcrumb() {
                echo '<ul id="crumbs">';
        if (!is_home()) {
                echo '<li><a href="';
                echo get_option('home');
                echo '">';
                echo 'Home';
                echo "</a></li>";
                if (is_category() || is_single()) {
                        echo '<li>';
                        the_category(' </li><li> ');
                        if (is_single()) {
                                echo "</li><li>";
                                the_title();
                                echo '</li>';
                        }
                } elseif (is_page()) {
                        echo '<li>';
                        echo the_title();
                        echo '</li>';
                }
        }
        elseif (is_tag()) {single_tag_title();}
        elseif (is_day()) {echo"<li>Archive for "; the_time('F jS, Y'); echo'</li>';}
        elseif (is_month()) {echo"<li>Archive for "; the_time('F, Y'); echo'</li>';}
        elseif (is_year()) {echo"<li>Archive for "; the_time('Y'); echo'</li>';}
        elseif (is_author()) {echo"<li>Author Archive"; echo'</li>';}
        elseif (isset($_GET['paged']) && !empty($_GET['paged'])) {echo "<li>Blog Archives"; echo'</li>';}
        elseif (is_search()) {echo"<li>Search Results"; echo'</li>';}
        echo '</ul>';
}

The Tag For the Invocation in the Theme

In the theme, the navigation can be integrated using a simple function invocation. The right files to do that would be the header.php, the index.php, or the single.php, depending on the theme.
<?php ah_the_breadcrumb(); ?>

26 - Display Custom Post Types in the Categories and Tags

Custom Post Types are an extremely useful tool for the design of an extensive website with many functions. However, they are not automatically included in the categories and tags. If you start a search, this will always leave you with an error. These two snippets integrate your custom post types into the WordPress search function. The Snippet for the Categories:
<?php

/**
 * Results in the display of the custom post types in the categories 
 * @author Andreas Hecht
 */
function evolution_query_post_type($query) {
  if( is_category() ) {
    $post_type = get_query_var('post_type');
    if($post_type)
        $post_type = $post_type;
    else
        // Adding your post types
        $post_type = array('nav_menu_item', 'post', 'posttype', 'posttype'); // don't forget nav_menu_item to allow menus to work!
    $query->set('post_type',$post_type);
    return $query;
    }
}
add_filter('pre_get_posts', 'evolution_query_post_type');
The Snippet for the Tags:
<?php

/**
 * Results in the display of the custom post types in the tags
 * @author Andreas Hecht
 */
function evolution_tag_query_post_type($query) {
  if( is_tag() ) {
    $post_type = get_query_var('post_type');
    if($post_type)
        $post_type = $post_type;
    else
        // Adding your post types
        $post_type = array('nav_menu_item', 'post', 'posttype', 'posttype'); // don't forget nav_menu_item to allow menus to work!
    $query->set('post_type',$post_type);
    return $query;
    }
}
add_filter('pre_get_posts', 'evolution_tag_query_post_type');

Conclusion

I hope you discovered some useful snippets for you and your WordPress. If this article ends up being successful, I might follow up with an article on the most useful WooCommerce snippets. Let me know whether that interests you. And if you're looking to hit the easy button and have your WordPress site fully managed for you, a WP Buffs 24/7 maintenance plan might be a good investment for you.

Andreas Hecht

Andreas Hecht is a journalist and specialist for WordPress and WordPress Security. He roams the web since its inception. He has published an ebook on WordPress Security, which you might want to take a look at.

One comment

  1. In snippet 3 – Turn Off WordPress Emojis – the 3rd function to remove DNS prefetch did not work for me, but this did:
    add_filter( ’emoji_svg_url’, ‘__return_false’ );

Leave a Reply

Your email address will not be published. Required fields are marked *