parsing nested blocks (in columns, etc) via PHP
-
20-05-2021 - |
Вопрос
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?
Решение
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
}
}
}