0

I have a parent theme that was developed as a project base, and within that I have been building up a group of completely custom WP Blocks (scaffolded with npx @wordpress/create-block).

These blocks work great when the parent theme is active, but if I activate a child theme, the blocks disappear.

The npx command creates a PHP file in the root with something like:

function create_block_custom_block_init() {
    register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'create_block_custom_block_init' );

And if I echo within that function the file path, the correct parent's file path is returned and all looks well. Unfortunately, the block just doesn't register or show in the inserter.

So from that, the init hook looks to be being called correctly, it's just that the function register_block_type doesn't want to run.

I'm aware the typical convention is to put blocks in a plugin, I'm hoping to keep them in the theme so blocks can't just be deactivated.

Has anyone any experience of this please?

Thanks, Ben

2 Answers 2

0

This is an issue from WordPress, persisting on the current 6.2.2 version.

The problem:

On wp-includes/blocks.php, there are 2 functions, register_block_script_handle and register_block_style_handle, that will try to register the block script and styles based on the file paths. Because those functions will not be checking to see if the folder is inside the parent theme, registered script and styles URLs are wrong, something like https://localhost/wp-content/plugins/var/www/htms/wp-content/themes/.....

The solution

Register those scripts and styles yourself and pass those as arguments to the register_block_type function.

Example:

function create_block_custom_block_init() {
    $block_config = include(__DIR__ . '/build/index.asset.php');
    $dependencies = $block_config['dependencies'];

    // register block script and styles. 
    wp_register_script("parent-theme-blocks-block-name-editor-script-js", get_template_directory_uri() . '/blocks/build/index.js', $dependencies, $block_config['version'], true);
    wp_register_style("parent-theme-blocks-block-name-editor-style", get_template_directory_uri() . "/blocks/build/index.css", array(), $block_config['version']);
    wp_register_style("parent-theme-blocks-block-name-style", get_template_directory_uri() . "/blocks/build/style-index.css", array(), $block_config['version']);

    $args = array(
        'api_version'     => 2,
        'attributes'      => ['your block attributes'],
        // Pass the registered script and styles handlers
        'editor_script'   => "parent-theme-blocks-block-name-editor-script-js",
        'editor_style'    => "parent-theme-blocks-block-name-editor-style",
        'style'           => "parent-theme-blocks-block-name-style",
    );

    register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'create_block_custom_block_init' );

Just make sure you modify the names and the URLs acrodig to your setup

1
  • Thanks Ovi, that has done the job for me!
    – Ben
    Jul 3, 2023 at 8:45
0

It sounds like the issue might be related to the way WordPress loads parent and child themes, and how it handles functions that are defined in both.

When a child theme is active, WordPress loads the functions.php file from the child theme first, and then loads the parent theme's functions.php file. If there is a function with the same name in both files, the function in the child theme will override the function in the parent theme.

In your case, it's possible that the child theme's functions.php file is defining a function with the same name as the create_block_custom_block_init function that is defined in the parent theme. When this happens, the child theme's version of the function will be used instead of the parent theme's version, which may cause the blocks to disappear.

To avoid this issue, you can try prefixing the function name in the parent theme with a unique string, such as the parent theme's name or a custom prefix. For example:

function parent_theme_prefix_create_block_custom_block_init() {
    register_block_type(DIR . '/build');
}
add_action('init', 'parent_theme_prefix_create_block_custom_block_init');

By prefixing the function name with a unique string, you can ensure that the function in the parent theme is not overridden by a function in the child theme with the same name.

If this doesn't solve the issue, you can also try using the wp_enqueue_script() function to load the block's JavaScript file in the parent theme's functions.php file. This can help ensure that the block's scripts are loaded correctly even when a child theme is active.

1
  • Thanks for your thoughts Jannickla. Sorry it took me a while to get back to you. We do prefix function names, but the function is actually firing correctly because I can echo the file path inside the function successfully. It seems to be an issue with the WP function register_block_type. I tried wp_enqueue_script() as suggested, the file appears in the site head but doesn't change anything.
    – Ben
    May 25, 2023 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.