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.
On this page
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:
| Function | Returns |
|---|---|
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.phpNotes:
require_onceavoids fatal "cannot redeclare" errors if a file is loaded twice.glob()returnsfalseon 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.