functions.php

If you’re using the child theme and need to add advanced custom features to your site, then the child theme’s functions.php (/wp-content/themes/chap-child/functions.php) is the most common place to add your code.

PHP knowledge required.

The contents of this file are completely up to you, how ever by default it is set up with some PHP namespaces and an action that includes the child theme’s style and script files.

PHP
Chap theme’s default functions.php
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);

}

namespace Chap\TemplateFunctions {

	/**
	 * Override any template function here.
	 */

}

Adding an action

With the PHP namespaces, all code should be contained within the brackets of a namespace. When adding an action you should specify the namespace in front of the function name that you’re adding.

PHP
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);
  
	/**
	 * Add a custom image size.
	 */
	function add_custom_image_size() {
		add_image_size('custom-image-size', 28, 28, true);
	}
	add_action('after_setup_theme', __NAMESPACE__ . '\\add_custom_image_size');

}

Alternatively, you could use the global namespace namespace { ... } without needing to prefix the function with the current namespace, how ever if any plugin anywhere uses the same function name (in this example add_custom_image_size()) then it will cause a conflict.

PHP
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);

}

namespace {

	/**
	 * Add a custom image size.
	 */
	function add_custom_image_size() {
		add_image_size('custom-image-size', 28, 28, true);
	}
	add_action('after_setup_theme', 'add_custom_image_size');

}

The simplest way would be to use anonymous functions directly as the second argument to add_action(), which saves you the trouble of defining a separate function and then assigning it. It looks much more compact and readable, how ever with this approach it is not possible to later conditionally remove that specific action with some other code.

PHP
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);
  
	/**
	 * Add a custom image size.
	 */
	add_action('after_setup_theme', function() {
		add_image_size('custom-image-size', 28, 28, true);
	});

}

Finally, you could opt out of all the namespaces by getting rid of them entirely:

PHP
<?php

/**
 * Load the child theme assets.
 */
function assets() {
	wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
	wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
}
add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);

/**
 * Add a custom image size.
 */
function add_custom_image_size() {
	add_image_size('custom-image-size', 28, 28, true);
}
add_action('after_setup_theme', 'add_custom_image_size');

or create a new file my-functions.php to house your unnamespaced code:

PHP
/wp-content/themes/chap-child/my-functions.php
<?php

/**
 * Add a custom image size.
 */
function add_custom_image_size() {
	add_image_size('custom-image-size', 28, 28, true);
}
add_action('after_setup_theme', 'add_custom_image_size');

and simply include it in the original functions.php:

PHP
Chap theme’s default functions.php
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);

	include_once 'my-functions.php';

}

All of the above applies for add_filter(), add_shortcode() etc as well.

Overriding theme core functions

Besides preventing conflicts, the PHP namespaces are also good for overriding Chap theme’s pluggable functions.

Hypothetically if you were looking around Chap source code for a way to add some text before the header you would come across this “pluggable function”:

PHP
/chap/lib/template-functions/action-chap-render-header.php
<?php

namespace Chap\TemplateFunctions;
use Chap\Options;
use Chap\Helpers;

if(!function_exists(__NAMESPACE__ . '\\chap_render_header_open')):
	/**
	 * Renders the header opening tag.
	 */
	function chap_render_header_open() {
		$header_classes = Helpers\classnames([
			'ui',
			'inverted' => Options\get('header_inverted'),
			'segment',
		]);

		?>
		<div class="<?php echo esc_attr($header_classes); ?>">
		<?php
	}
endif;

You couldn’t modify this function directly because theme updates would just overwrite it, but since the function checks whether or not it exists before creating it you could add your own version to the child theme’s functions.php in the same namespace that it originates from, in this case Chap\TemplateFunctions.

PHP
/chap-child/functions.php
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);

}

namespace Chap\TemplateFunctions {
	use Chap\Options;
	use Chap\Helpers;

	/**
	 * Custom header opening tag function.
	 */
	function chap_render_header_open() {
		$header_classes = Helpers\classnames([
			'ui',
			'inverted' => Options\get('header_inverted'),
			'segment',
		]);

		?>
		Custom content before header opening tag.
		<div class="<?php echo esc_attr($header_classes); ?>">
		<?php
	}

}

If the function utilizes Chap functions from other namespaces don’t forget to “use” them as well: use Chap\Options;

Alternatively they can be called directly by specifying the full namespace \Chap\Helpers\function():

PHP
/chap-child/functions.php
<?php

namespace Chap\Child {

	/**
	 * Load the child theme assets.
	 */
	function assets() {
		wp_enqueue_style('chap-child', get_stylesheet_directory_uri() . '/style.css', false, wp_get_theme()->get('Version'));
		wp_enqueue_script('chap-child/js', get_stylesheet_directory_uri() . '/scripts.js', ['chap/js'], wp_get_theme()->get('Version'), true);
	}
	add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 150);

}

namespace Chap\TemplateFunctions {

	/**
	 * Custom header opening tag function.
	 */
	function chap_render_header_open() {
		$header_classes = \Chap\Helpers\classnames([
			'ui',
			'inverted' => \Chap\Options\get('header_inverted'),
			'segment',
		]);

		?>
		Custom content before header opening tag.
		<div class="<?php echo esc_attr($header_classes); ?>">
		<?php
	}

}

2 responses to “functions.php

Leave a comment

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