0

I'm checking posts for a custom block and trying to render the content of those blocks elsewhere in the site via PHP. My method for doing that looks like this:

      if ( has_block( 'custom/block' ) ) {
        global $post;

        $blocks = parse_blocks( $post->post_content );
        foreach ( $blocks as $block ) {
          if ( 'custom/block' === $block['blockName'] ) {
              echo "<div>";
              echo apply_filters( 'the_content', render_block( $block ) );
              echo "</div>";
              break;
          } 
      }

So I basically check the post for a specific block, when I find it I output its contents, then break the loop because I only care about the first one. The problem is that when you put the 'custom/block' in a column block (or anything similar I'm assuming) then this loop will miss it. I'm not sure how to effectively investigate a block's innerblocks to solve this problem, other than something like iterating over all possible parent blocks and checking their guts like so:

      if ( has_block( 'custom/block' ) ) {
        global $post;

        $blocks = parse_blocks( $post->post_content );
        foreach ( $blocks as $block ) {
          if ( 'custom/block' === $block['blockName'] ) {
              echo "<div>";
              echo apply_filters( 'the_content', render_block( $block ) );
              echo "</div>";
              break;
          } elseif ( 'core/columns' === $block['blockName'] ) {
            $column = apply_filters( 'the_content', render_block( $block ) );
            // mess around with the $column here to get the appropriate equivalent output
          }
          // elseif iterate through other potential parent blocks
      }

Any suggestions to make this less messy?

1

If I understand it correctly, you can use a recursive function which loops through inner blocks to find the specific block. Example:

/* Sample usage, assuming $post is defined properly:

    $blocks = parse_blocks( $post->post_content );
    wpse_387661( $blocks );
*/
function wpse_387661( $blocks ) {
    foreach ( $blocks as $block ) {
        if ( ! empty( $block['innerBlocks'] ) ) {
             wpse_387661( $block['innerBlocks'] );
        } elseif ( 'custom/block' === $block['blockName'] ) {
            echo apply_filters( 'the_content', render_block( $block ) );
            break; // this could mean that inner blocks were never looped
        }
    }
}
1
  • 1
    Yep, that appears to do it! Thanks! – jshwlkr May 5 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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