has_block( string $block_name, int|string|WP_Post|null $post = null )

Determine whether a $post or a string contains a specific block type.


Description Description

This test optimizes for performance rather than strict accuracy, detecting whether the block type exists but not validating its structure and not checking reusable blocks. For strict accuracy, you should use the block parser on post content.

See also See also


Top ↑

Parameters Parameters

$block_name

(string) (Required) Full block type to look for.

$post

(int|string|WP_Post|null) (Optional) Post content, post ID, or post object. Defaults to global $post.

Default value: null


Top ↑

Return Return

(bool) Whether the post content contains the specified block.


Top ↑

Source Source

File: wp-includes/blocks.php

function has_block( $block_name, $post = null ) {
	if ( ! has_blocks( $post ) ) {
		return false;
	}

	if ( ! is_string( $post ) ) {
		$wp_post = get_post( $post );
		if ( $wp_post instanceof WP_Post ) {
			$post = $wp_post->post_content;
		}
	}

	/*
	 * Normalize block name to include namespace, if provided as non-namespaced.
	 * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
	 * their serialized names.
	 */
	if ( false === strpos( $block_name, '/' ) ) {
		$block_name = 'core/' . $block_name;
	}

	// Test for existence of block by its fully qualified name.
	$has_block = false !== strpos( $post, '<!-- wp:' . $block_name . ' ' );

	if ( ! $has_block ) {
		/*
		 * If the given block name would serialize to a different name, test for
		 * existence by the serialized form.
		 */
		$serialized_block_name = strip_core_block_namespace( $block_name );
		if ( $serialized_block_name !== $block_name ) {
			$has_block = false !== strpos( $post, '<!-- wp:' . $serialized_block_name . ' ' );
		}
	}

	return $has_block;
}


Top ↑

Changelog Changelog

Changelog
Version Description
5.0.0 Introduced.

Top ↑

User Contributed Notes User Contributed Notes

  1. Skip to note 4 content

    The function doesn’t work in reusable blocks. If you need to check blocks within a reusable block you need to parse content first. Here is my simplified functional solution (although OOP would do bit better):

    /**
     * Has block function which searches as well in reusable blocks.
     *
     * @param mixed $block_name Full Block type to look for.
     * @return bool
     */
    function wpdocs_enhanced_has_block( $block_name ) {
    	if ( has_block( $block_name ) ) {
    		return true;
    	}
    
    	if ( has_block( 'core/block' ) ) {
    		$content = get_post_field( 'post_content' );
    		$blocks = parse_blocks( $content );
    		return wpdocs_search_reusable_blocks_within_innerblocks( $blocks, $block_name );
    	}
    
    	return false;
    }
    
    /**
     * Search for the selected block within inner blocks.
     *
     * The helper function for wpdocs_enhanced_has_block() function.
     *
     * @param array $blocks Blocks to loop through.
     * @param string $block_name Full Block type to look for.
     * @return bool
     */
    function wpdocs_search_reusable_blocks_within_innerblocks( $blocks, $block_name ) {
    	foreach ( $blocks as $block ) {
    		if ( isset( $block['innerBlocks'] ) && ! empty( $block['innerBlocks'] ) ) {
    			wpdocs_search_reusable_blocks_within_innerblocks( $block['innerBlocks'], $block_name );
    		} elseif ( 'core/block' === $block['blockName'] && ! empty( $block['attrs']['ref'] ) && has_block( $block_name, $block['attrs']['ref'] ) ) {
    			return true;
    		}
    	}
    
    	return false;
    }

    Now you can call wpdocs_enhanced_has_block( 'core/heading' ) to check for heading block both in post content and if not found in all reusable blocks within the post.

You must log in before being able to contribute a note or feedback.