Skip to content
Skip to the article
In WordPress: 10 articles
WordPress

Split a child theme's functions.php into included files

Keep functions.php short by loading feature files and whole folders of post type and taxonomy definitions from the child theme.

Updated
Applies to
  • WordPress 6.x
Tags
  • wordpress
  • themes
  • php
Reading time
2 min

A functions.php that grows past a few hundred lines is hard to review. This pattern keeps it as a short loader that pulls in one file per feature, plus every file in a folder for things like custom post types and taxonomies.

Pick the Right Path Function

The most common bug in child themes is loading files from the wrong theme. Use the function that matches where the file lives:

FunctionReturns
get_stylesheet_directory()The active (child) theme's folder.
get_template_directory()The parent theme's folder.
get_theme_file_path( 'file.php' )The child theme's copy if it exists, otherwise the parent's.

In a child theme, get_template_directory() points at the parent, so files you add to the child theme won't be found.

Loader Pattern

Put this in the child theme's functions.php:

<?php
/**
 * Child theme loader.
 */

// Single feature files.
require_once get_stylesheet_directory() . '/inc/block-styles.php';
require_once get_stylesheet_directory() . '/inc/woocommerce.php';

// Every file in a folder (loaded in alphabetical order).
foreach ( [ 'post-types', 'taxonomies' ] as $folder ) {
	foreach ( glob( get_stylesheet_directory() . "/{$folder}/*.php" ) ?: [] as $file ) {
		require_once $file;
	}
}

With a layout like:

my-child-theme/
├── functions.php
├── style.css
├── inc/
│   ├── block-styles.php
│   └── woocommerce.php
├── post-types/
│   └── my-cpt.php
└── taxonomies/
    └── my-taxonomy.php

Notes:

  • require_once avoids fatal "cannot redeclare" errors if a file is loaded twice.

  • glob() returns false on some systems when it fails, so ?: [] keeps the loop safe.

  • glob() sorts results alphabetically. If one file depends on another, prefix them (10-base.php, 20-extra.php).

  • Each included file should register its own hooks (for example add_action( 'init', ... ) to register a post type) rather than running code immediately.

Tip

Custom post types and taxonomies hold content, so they usually belong in a small site plugin or must-use plugin rather than a theme. If they live in the theme, switching themes makes that content disappear from the admin. The same loader works in a plugin. Use plugin_dir_path( __FILE__ ) in place of get_stylesheet_directory().

See Custom Post Type Admin for an example post type file.

Sources

This article is in the public domain (CC0 1.0), code samples included. Use it however helps you.