Error when using custom functions or classes in WordPress block patterns registered via the patterns folder

Just a quick post since I lost an hour to this today and there wasn’t a lot of good results to save me from myself when Googling.

I’m building my first WordPress block theme and using patterns to allow for some good old fashioned PHP alongside all the new HTML template parts, thus somewhat replicating the partials structure of classic themes.

I ran into an issue where doing a database pull using Pantheon’s (excellent) tool Lando for local development was failing, spitting out an error:

PHP Fatal error:  Uncaught Error: Class 'bootstrap_5_wp_nav_menu_walker' not found in /app/wp-content/themes/acme-theme/patterns/header.php:30
Stack trace:
#0 /app/wp-includes/block-patterns.php(325): include()
#1 /app/wp-includes/class-wp-hook.php(308): _register_theme_block_patterns('')
#2 /app/wp-includes/class-wp-hook.php(332): WP_Hook->apply_filters(NULL, Array)
#3 /app/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#4 /app/wp-settings.php(617): do_action('init')
#5 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1336): require('/app/wp-setting...')
#6 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1254): WP_CLI\Runner->load_wordpress()
#7 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php(28): WP_CLI\Runner->start()
#8 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/bootstrap.php(78): WP_CLI\Bootstrap\LaunchRunner->process(Object(WP_CLI\Bootstrap\BootstrapState))
#9 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/wp-cli.php(3 in /app/wp-content/themes/acme-theme/patterns/header.php on line 30
Fatal error: Uncaught Error: Class 'bootstrap_5_wp_nav_menu_walker' not found in /app/wp-content/themes/acme-theme/patterns/header.php:30

I was temporarily stumped since bootstrap_5_wp_nav_menu_walker was successfully registered and called in functions.php and the theme worked properly in a remote dev environment.

Finally figured it out by going to the source and rereading WordPress’s documentation on block patterns. In the alternate registration method, you can use function_exists or class_exists wrapped around your register function, but since blocks in the patterns/ directory are autoloaded first, I need to do that check in the pattern itself. So adding a simple class_exists() check fixed my issue. Duh.

if (class_exists('bootstrap_5_wp_nav_menu_walker')) {
  $walker = new bootstrap_5_wp_nav_menu_walker();
} else {
  $walker = '';
}
wp_nav_menu(array(
    'theme_location' => 'main-menu',
    'container' => false,
    'menu_class' => '',
    'fallback_cb' => '__return_false',
    'items_wrap' => '<ul id="%1$s" class="navbar-nav ms-auto mb-2 mb-md-0 %2$s">%3$s</ul>',
    'depth' => 2,
    'walker' => $walker,
));

Probably should have figured that out sooner, but since I knew it existed in my functions.php I was caught out by the order patterns were registered.

Leave a Comment