Recommended functions.php Patterns
warning
Child theme code runs on every request. A fatal error or heavy logic will impact the entire site.
Recommended functions.php Patterns Explained
| Pattern | What it looks like | Why it helps |
|---|---|---|
| Modular includes | require_once .../inc/*.php | Prevents functions.php bloat |
| Scoped hooks | One file for hooks, one for filters | Easier debugging |
| Prefixes/namespaces | Unique identifiers | Avoid collisions |
| Guard rails | ABSPATH guard, early returns | Safer execution |
Why It Matters
- Maintainability: teams can navigate code faster.
- Safety: smaller files reduce error surface.
- Deployability: modular child themes are easier to test and review.
How It Works
functions.php is the entry point for child theme code. It should bootstrap only: includes, constants, and hooks.
flowchart TD
F[functions.php] --> INC[inc/*.php includes]
INC --> ENQ[Enqueues]
INC --> HOOKS[Hooks]
INC --> FIL[Filters]
HOOKS --> OUT[Site output]
Practical Walkthrough
Step 1: Create a Minimal inc/ Layout
create-inc-layout.sh
cd /var/www/html
mkdir -p wp-content/themes/generatepress-child/inc
touch wp-content/themes/generatepress-child/inc/enqueue.php
touch wp-content/themes/generatepress-child/inc/hooks.php
touch wp-content/themes/generatepress-child/inc/filters.php
Step 2: Bootstrap Includes from functions.php
wp-content/themes/generatepress-child/functions.php
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
require_once get_stylesheet_directory() . '/inc/enqueue.php';
require_once get_stylesheet_directory() . '/inc/hooks.php';
require_once get_stylesheet_directory() . '/inc/filters.php';
Step 3: Put Enqueues in inc/enqueue.php
wp-content/themes/generatepress-child/inc/enqueue.php
<?php
add_action( 'wp_enqueue_scripts', function() {
wp_enqueue_style( 'generatepress-parent', get_template_directory_uri() . '/style.css' );
} );
Step 4: Verify Your Child Theme Structure
verify-child-theme-structure.sh
cd /var/www/html/wp-content/themes/generatepress-child
ls
ls inc
Practical Examples
Example 1: Prefix a Custom Function
wp-content/themes/generatepress-child/inc/hooks.php
<?php
function gp_child_notice() {
echo '<div class="gp-child-notice">Hello</div>';
}
add_action( 'generate_before_header', 'gp_child_notice' );
Example 2: Keep Debug Code Behind a Flag
Use a constant or environment flag so debug output does not ship accidentally.
wp-content/themes/generatepress-child/functions.php
<?php
define( 'GP_CHILD_DEBUG', false );
wp-content/themes/generatepress-child/inc/hooks.php
<?php
if ( defined( 'GP_CHILD_DEBUG' ) && GP_CHILD_DEBUG ) {
add_action( 'wp_footer', function() {
echo '<!-- GP child debug enabled -->';
} );
}
Example 3: Put Filters in inc/filters.php
wp-content/themes/generatepress-child/inc/filters.php
<?php
add_filter( 'body_class', function( $classes ) {
$classes[] = 'gp-child';
return $classes;
} );
Best Practices
| Practice | Why |
|---|---|
Keep functions.php as a bootstrap only | Easier audits |
Use require_once (not require) | Prevents double include bugs |
| Prefer hooks/filters over template copies | Update safety |
| Escape output | Security |
| Keep heavy logic out of hooks | Protects performance |
| Avoid hard-coded paths | Use get_stylesheet_directory() helpers |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Fatal error after deploy | Missing include file | Confirm paths and re-deploy |
| Hook runs twice | Included twice | Ensure require_once and no duplicates |
| White screen | Syntax error | Check /usr/local/lsws/logs/error.log |
| "Cannot redeclare" errors | Function loaded twice | Use unique prefixes/namespaces and remove duplicates |
Hands-On
- Split your child theme into
inc/enqueue.php,inc/hooks.php, andinc/filters.php. - Add one hook in
inc/hooks.php. - Confirm it renders, then remove it.
- Add one filter in
inc/filters.phpand confirm it changes output (body class).
Quick Reference
functions-php-patterns-cheatsheet.sh
cd /var/www/html/wp-content/themes/generatepress-child
ls
ls inc
What's Next
- Next: Overriding Templates Safely
- Related: Hooks Overview