Adding Dynamic Functionality
Block Themes & PHP
Block themes can still use functions.php for:
- Custom functionality
- Block registration
- Action/filter hooks
- External integrations
Setting Up functions.php
get( 'Version' )
);
// JavaScript
wp_enqueue_script(
'my-theme-scripts',
get_template_directory_uri() . '/assets/js/main.js',
array(),
wp_get_theme()->get( 'Version' ),
true
);
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_assets' );
/**
* Enqueue editor assets
*/
function my_theme_enqueue_editor_assets() {
wp_enqueue_style(
'my-theme-editor',
get_template_directory_uri() . '/assets/css/editor.css',
array(),
wp_get_theme()->get( 'Version' )
);
}
add_action( 'enqueue_block_editor_assets', 'my_theme_enqueue_editor_assets' );Custom Block Styles
/**
* Register custom block styles
*/
function my_theme_register_block_styles() {
register_block_style(
'core/button',
array(
'name' => 'gradient',
'label' => __( 'Gradient', 'my-theme' ),
)
);
register_block_style(
'core/image',
array(
'name' => 'shadow',
'label' => __( 'With Shadow', 'my-theme' ),
)
);
register_block_style(
'core/group',
array(
'name' => 'card',
'label' => __( 'Card', 'my-theme' ),
)
);
}
add_action( 'init', 'my_theme_register_block_styles' );Style them in CSS:
/* Button gradient style */
.wp-block-button.is-style-gradient .wp-block-button__link {
background: linear-gradient(135deg, var(--wp--preset--color--primary) 0%, var(--wp--preset--color--secondary) 100%);
}
/* Image shadow style */
.wp-block-image.is-style-shadow img {
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
}
/* Group card style */
.wp-block-group.is-style-card {
padding: var(--wp--preset--spacing--30);
background: var(--wp--preset--color--light);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}Block Variations
/**
* Register block variations
*/
function my_theme_register_block_variations() {
wp_enqueue_script(
'my-theme-block-variations',
get_template_directory_uri() . '/assets/js/block-variations.js',
array( 'wp-blocks', 'wp-dom-ready' ),
wp_get_theme()->get( 'Version' ),
true
);
}
add_action( 'enqueue_block_editor_assets', 'my_theme_register_block_variations' );// assets/js/block-variations.js
wp.domReady(() => {
wp.blocks.registerBlockVariation('core/columns', {
name: 'three-equal',
title: 'Three Equal Columns',
icon: 'columns',
scope: ['inserter'],
innerBlocks: [
['core/column', { width: '33.33%' }],
['core/column', { width: '33.33%' }],
['core/column', { width: '33.33%' }],
],
});
wp.blocks.registerBlockVariation('core/group', {
name: 'section',
title: 'Section',
icon: 'align-wide',
scope: ['inserter'],
attributes: {
align: 'full',
style: {
spacing: {
padding: {
top: 'var:preset|spacing|50',
bottom: 'var:preset|spacing|50',
}
}
}
},
});
});Custom Render Callbacks
Add dynamic content to templates:
/**
* Register dynamic block
*/
function my_theme_register_dynamic_blocks() {
register_block_type( 'my-theme/current-year', array(
'render_callback' => 'my_theme_render_current_year',
) );
}
add_action( 'init', 'my_theme_register_dynamic_blocks' );
function my_theme_render_current_year( $attributes, $content ) {
return '<span class="current-year">' . date( 'Y' ) . '</span>';
}Use in templates:
<!-- wp:paragraph -->
<p>ยฉ <!-- wp:my-theme/current-year /--> Your Company. All rights reserved.</p>
<!-- /wp:paragraph -->Block Bindings API (WP 6.5+)
Connect block attributes to dynamic data:
/**
* Register custom block bindings
*/
add_action( 'init', function() {
register_block_bindings_source( 'my-theme/meta', array(
'label' => __( 'Post Meta', 'my-theme' ),
'get_value_callback' => function( $source_args, $block_instance ) {
if ( empty( $source_args['key'] ) ) {
return '';
}
return get_post_meta( get_the_ID(), $source_args['key'], true );
},
) );
} );Use in templates:
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"my-theme/meta","args":{"key":"subtitle"}}}}} -->
<p></p>
<!-- /wp:paragraph -->Theme Hooks
/**
* Before header
*/
function my_theme_before_header() {
// Add announcement bar, skip links, etc.
echo '<a class="skip-link" href="#main">' . __( 'Skip to content', 'my-theme' ) . '</a>';
}
add_action( 'wp_body_open', 'my_theme_before_header' );
/**
* Modify block content
*/
function my_theme_modify_block_content( $block_content, $block ) {
if ( 'core/image' === $block['blockName'] ) {
// Add lazy loading attributes, etc.
}
return $block_content;
}
add_filter( 'render_block', 'my_theme_modify_block_content', 10, 2 );Next Steps
In the final lesson, we'll cover packaging and distributing your block theme.
๐ฏ Lesson Complete! You can now add dynamic functionality to your block theme with PHP.