Code Snippets

We all agree that WordPress plugins are useful and simplify many situations. But sometimes a few lines in your theme's functions.php file can save you from adding yet another plugin to your site.

In this archive you'll find a wide variety of code snippets that allow modifications and customizations to WordPress and how it works. These are short, practical code snippets collected over the years.

Every time I come across a useful snippet I add it to the collection, so if you have a specific snippet you'd like to share, feel free to send it over and I'll add it to the list.

Disable Pingbacks and Trackbacks in WordPress

Pingbacks and trackbacks are a legacy WordPress mechanism that notifies other sites when you link to them. In practice, most pingbacks are spam and there is no reason to keep the feature enabled. For more on hardening WordPress security.

Disable pingbacks via code – add to functions.php:

add_filter( 'xmlrpc_methods', function( $methods ) {
	unset( $methods['pingback.ping'] );
	unset( $methods['pingback.extensions.getPingbacks'] );
	return $methods;
} );

add_action( 'pre_ping', function( &$links ) {
	$home = get_option( 'home' );
	foreach ( $links as $l => $link ) {
		if ( strpos( $link, $home ) === 0 ) {
			unset( $links[ $l ] );
		}
	}
} );

Also disable the option in Settings > Discussion > uncheck “Allow link notifications from other blogs (pingbacks and trackbacks)”.

Change Currency Symbol in WooCommerce

If you want to change the currency symbol WooCommerce displays (e.g. replace “$” with “USD” or add a space), add the following code to your functions.php file. For more on WooCommerce hooks.

add_filter( 'woocommerce_currency_symbol', function( $symbol, $currency ) {
	switch ( $currency ) {
		case 'USD':
			$symbol = 'USD ';
			break;
		case 'GBP':
			$symbol = 'GBP ';
			break;
	}
	return $symbol;
}, 10, 2 );

Modify the case and $symbol values to match your needs.

Add a Custom WP-Cron Interval in WordPress

WordPress core ships with four WP-Cron intervals: hourly, twicedaily, daily and weekly. If you need anything else, such as every 5 minutes, register a custom interval with the cron_schedules filter and then schedule your event with wp_schedule_event().

The order matters. The custom interval has to exist before you schedule an event that uses it, otherwise WordPress rejects the event.

Add a Custom Cron Interval

Add this to your child theme’s functions.php or to a plugin. It registers a 5-minute interval, schedules one recurring event on it, and attaches the task.

// 1. Register the interval.
add_filter( 'cron_schedules', function ( $schedules ) {
	$schedules['every_five_minutes'] = array(
		'interval' => 5 * MINUTE_IN_SECONDS,
		'display'  => 'Every 5 Minutes',
	);
	return $schedules;
} );

// 2. Schedule the event once, if it isn't scheduled yet.
add_action( 'init', function () {
	if ( ! wp_next_scheduled( 'my_custom_cron_event' ) ) {
		wp_schedule_event( time(), 'every_five_minutes', 'my_custom_cron_event' );
	}
} );

// 3. The task that runs on each interval.
add_action( 'my_custom_cron_event', function () {
	// Your code here.
} );

How It Works

The cron_schedules filter lets you add entries to the list of recurrences. Each entry needs a unique key, an interval in seconds, and a display label shown by tools like WP-CLI.

wp_schedule_event( $timestamp, $recurrence, $hook ) stores the event. The first run happens at $timestamp, then every interval after that. The wp_next_scheduled() check prevents a duplicate event on every page load.

When the event is due, WordPress fires the hook name you passed, so any function attached with add_action() runs. For a refresher on actions and filters, see WordPress hooks explained.

WordPress Default Cron Intervals

These recurrences are available without any filter. The weekly schedule was added in WordPress 5.4.

Key Interval (seconds) Display name
hourly 3600 Once Hourly
twicedaily 43200 Twice Daily
daily 86400 Once Daily
weekly 604800 Once Weekly

So for a weekly task on WordPress 5.4 or later, skip the filter and pass 'weekly' directly, as in this weekly transient cleanup. You also can’t redefine these four keys, core defaults override filter entries with the same name.

Common Mistakes

Most WP-Cron problems with custom intervals come down to one of these.

  • Scheduling before the filter exists. If the interval isn’t registered when wp_schedule_event() runs, it returns false (or a WP_Error with code invalid_schedule when you pass true as the fifth argument).
  • Switching the event to another schedule key. If you change 'every_five_minutes' in the wp_schedule_event() call, the existing event keeps its old recurrence, because wp_next_scheduled() still finds it. Run wp_clear_scheduled_hook( 'my_custom_cron_event' ) once, then let the code schedule it again.
  • Not cleaning up. In a plugin, clear the hook on deactivation with register_deactivation_hook() so the event doesn’t keep firing into nothing.
  • Expecting exact timing. WP-Cron only runs when someone visits the site, so a 5-minute task on a quiet site runs late.

For reliable timing, set DISABLE_WP_CRON to true and trigger cron from the server instead. The steps are in Disable WP-Cron and use a real server cron job.

To check that your interval and event were registered, run these WP-CLI commands:

wp cron schedule list
wp cron event list

The full parameter list is in the wp_schedule_event() reference.

FAQs

Common questions about custom WP-Cron intervals:

What are the default cron intervals in WordPress?
hourly, twicedaily, daily and weekly. The weekly interval exists since WordPress 5.4, so older tutorials list only three.
Must the cron_schedules filter be added before wp_schedule_event()?
Yes. wp_schedule_event() validates the recurrence against the registered schedules at the moment it runs. If your filter isn't attached yet, the event isn't scheduled.
Why doesn't my custom cron event run on time?
WP-Cron is triggered by page visits, not by the clock. On low-traffic sites, disable it with DISABLE_WP_CRON and call wp-cron.php or wp cron event run --due-now from a server cron job.
How do I remove a scheduled cron event?
Call wp_clear_scheduled_hook( 'my_custom_cron_event' ), or run wp cron event delete my_custom_cron_event with WP-CLI. Also remove the scheduling code, or it will add the event back on the next page load.

Hide Out of Stock Products in WooCommerce

You can hide out-of-stock products from catalog and search pages. The simplest way is through WooCommerce settings: WooCommerce > Settings > Products > Inventory > “Hide out of stock items from the catalog”. If you prefer a code-based approach, add to your functions.php. For more on managing stock in WooCommerce.

add_action( 'pre_get_posts', function( $query ) {
	if ( ! is_admin() && $query->is_main_query() && ( is_shop() || is_product_category() || is_product_tag() ) ) {
		$query->set( 'meta_query', array(
			array(
				'key'     => '_stock_status',
				'value'   => 'instock',
				'compare' => '=',
			),
		) );
	}
} );

Increase WordPress Upload Max File Size

WordPress limits the file size you can upload through the Media Library. The limit is set by PHP settings on the server. Here are three ways to increase it. For more on troubleshooting image upload errors.

Option 1 – .htaccess file:

php_value upload_max_filesize 64M
php_value post_max_size 64M
php_value max_execution_time 300
php_value max_input_time 300

Option 2 – wp-config.php file:

@ini_set( 'upload_max_filesize', '64M' );
@ini_set( 'post_max_size', '64M' );
@ini_set( 'max_execution_time', '300' );

Option 3 – php.ini file:

upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300

Replace 64M with your desired size.

Increase WordPress Memory Limit

If you encounter the “Allowed memory size exhausted” error, increase the WordPress memory limit. Add the following lines to your wp-config.php file before the “That’s all, stop editing!” line. For more on optimizing wp-config.php.

define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

WP_MEMORY_LIMIT affects the frontend and WP_MAX_MEMORY_LIMIT affects the admin area. If the change does not help, your hosting provider may enforce a server-level limit.

Set Minimum Order Amount in WooCommerce

If you want to require a minimum order amount in your WooCommerce store, add the following code to your functions.php file. The code displays a notice in the cart and prevents checkout. For more on WooCommerce hooks.

add_action( 'woocommerce_checkout_process', function() {
	$minimum = 50;
	if ( WC()->cart->get_subtotal() < $minimum ) {
		wc_add_notice(
			sprintf( 'The minimum order amount is %s. Your current cart total is %s.',
				wc_price( $minimum ),
				wc_price( WC()->cart->get_subtotal() )
			), 'error'
		);
	}
} );

add_action( 'woocommerce_before_cart', function() {
	$minimum = 50;
	if ( WC()->cart->get_subtotal() < $minimum ) {
		wc_print_notice(
			sprintf( 'The minimum order amount is %s. Please add more products to your cart.',
				wc_price( $minimum )
			), 'notice'
		);
	}
} );

Replace 50 with your desired minimum amount.

Remove Related Products in WooCommerce

WooCommerce displays related products at the bottom of the product page by default. To remove them, add the following code to your functions.php file. For more on WooCommerce hooks.

remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );

If you only want to change the number of related products displayed instead of removing them entirely:

add_filter( 'woocommerce_output_related_products_args', function( $args ) {
	$args['posts_per_page'] = 3;
	$args['columns'] = 3;
	return $args;
} );

Force HTTPS Redirect via .htaccess in WordPress

To force HTTPS in WordPress on an Apache or LiteSpeed server, add a 301 redirect rule to your .htaccess file. Every HTTP request then goes to the same URL on HTTPS, so users and search engines see one version of each page.

Install the SSL certificate first and confirm the HTTPS version loads without errors. For the full move, including mixed content, see the guide on migrating your WordPress site to HTTPS.

The .htaccess Rule to Force HTTPS

Open the .htaccess file in the WordPress root (the folder that holds wp-config.php) and add these lines at the very top, above the # BEGIN WordPress block:

# Force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# BEGIN WordPress
# (the rules WordPress generated stay here, unchanged)
# END WordPress

Keep it outside the WordPress markers. WordPress rewrites everything between them when permalinks are saved.

How the Rule Works

What each part does:

  • RewriteCond %{HTTPS} off matches requests that did not arrive over SSL/TLS. Apache sets HTTPS to on for encrypted connections.
  • RewriteRule ^(.*)$ matches any path and sends it to https:// plus the requested host and path. The query string is carried over automatically.
  • R=301 makes the redirect permanent, which tells search engines to index the HTTPS URL. Without a code, Apache sends a temporary 302. L stops the remaining rules for this request.

The rule has to run before the WordPress block. Those rules route most requests to index.php, and a redirect placed after them never fires for normal post and page URLs.

Browsers cache 301 redirects hard. While testing, use R=302, check a few URLs, then switch to R=301.

Update the WordPress URLs to HTTPS

WordPress still builds links from its own settings. Go to Settings > General and change both WordPress Address (URL) and Site Address (URL) to https://.

If those fields are greyed out, the values are defined in wp-config.php. Update them there:

define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com' );

Old http:// links in post content cause mixed content warnings. With WP-CLI you can replace them in the database (back up first, and remove --dry-run when the report looks right):

wp search-replace 'http://example.com' 'https://example.com' --skip-columns=guid --dry-run

To also settle on one hostname, add the rules to redirect www to non-www (or the reverse).

Redirect Loops Behind Cloudflare, a Proxy or a Load Balancer

When SSL ends at a proxy or load balancer, the proxy talks to your server over plain HTTP. %{HTTPS} is always off, every request is redirected, and the browser shows “too many redirects”.

Check the X-Forwarded-Proto header the proxy sends instead of %{HTTPS}:

# Force HTTPS behind a proxy that sets X-Forwarded-Proto
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Only rely on this header when you control the proxy and it overwrites the header on every request. The Apache documentation on forcing HTTPS covers this setup and its caveat.

WordPress also needs to know the original request was HTTPS. Add this to wp-config.php above the “That’s all, stop editing!” line:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) {
    $_SERVER['HTTPS'] = 'on';
}

On Cloudflare, the usual cause is the Flexible SSL/TLS mode, where Cloudflare connects to your server over HTTP. Set the mode to Full (strict) with a valid certificate on the server, as described in Cloudflare’s redirect loop troubleshooting.

Nginx Does Not Read .htaccess

On Nginx, .htaccess files are ignored, so the rule above does nothing. Add a server block that listens on port 80 and redirects to HTTPS:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Without access to the server configuration, ask your host to add the redirect.

FAQs

Common questions about forcing HTTPS in WordPress:

Where in .htaccess should the force HTTPS rule go?
At the top of the file, above # BEGIN WordPress. Placed after the WordPress rules it never runs for post and page URLs, and placed inside the WordPress markers it gets overwritten when permalinks are saved.
Why do I get "too many redirects" after forcing HTTPS?
SSL is usually ending at a proxy such as Cloudflare, so your server sees every request as HTTP and keeps redirecting. Check X-Forwarded-Proto instead of %{HTTPS}, and on Cloudflare switch the SSL/TLS mode from Flexible to Full (strict).
Should the HTTPS redirect be a 301 or a 302?
Use a 301 for the live site, since the move to HTTPS is permanent and search engines should index the HTTPS URLs. Use a 302 while testing, because browsers cache 301 redirects.
Does the .htaccess redirect fix mixed content warnings?
No. Mixed content comes from http:// URLs inside your pages, such as images in post content. Update the WordPress Address and Site Address to HTTPS and replace old URLs in the database.

Disable WP-Cron and Use a Real Server Cron Job

WP-Cron runs on every page load, which can cause overhead on high-traffic sites or missed events on low-traffic sites. You can disable it and use a real server cron job instead. For more on optimizing wp-config.php.

Step 1 – Add to wp-config.php:

define( 'DISABLE_WP_CRON', true );

Step 2 – Set up a server cron job (every 5 minutes):

*/5 * * * * wget -q -O /dev/null https://your-domain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Replace your-domain.com with your domain.