-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to: Access InnerBlocks.Content in PHP #7247
Comments
Hi @manake, This file in one of my plugins may help you: In particular these two blocks of code:
Then you can grab the content in this function:
Note that I use a namespace in the plugin which is needed when calling the function. |
@mattwatsoncodes Another example, in one of my blocks I have multiple
|
Any workaround for accessing InnerBlocks.Content in php yet? |
@rameezwp We implemented a small polyfill for that problem: Gutenberg hooks into "the_content" to parse the Block-Comments. We also hooked in with preference 0 so that our filter starts first. Then we have a look into the Gutenberg Block Registry, look for our tags with inner content and called the registered callback ourself. Since Gutenberg Block Meta Comments are very structured, the needed regular expressions to identify tags and inner content were found very easely. We did that only for nested Gutenberg Blocks and left single tags to the Gutenberg filter. The solution has the benefit that you can work as documented by gutenberg and just turn off your filter as soon as the Gutenberg team has solved that issue. BR from Salzburg! |
So how I can actually render innerblocks from php callback? block.js Thanks for your help. |
Attempt three at including positional information from the parse to enable isomorphic reconstruction of the source `post_content` after parsing. See alternate attempts: #11082, #11309 Motivated by: #7247, #8760, Automattic/jetpack#10256 Enables: #10463, #10108 ## Abstract Add new `innerContent` property to each block in parser output indicating where in the innerHTML each innerBlock was found. ## Status - will update fixtures after design review indicates this is the desired approach - all parsers passing new tests for fragment behavior ## Summary Inner blocks, or nested blocks, or blocks-within-blocks, can exist in Gutenberg posts. They are serialized in `post_content` in place as normal blocks which exist in between another block's comment delimiters. ```html <!-- wp:outerBlock --> Check out my <!-- wp:voidInnerBlock /--> and my other <!-- wp:innerBlock --> with its own content. <!-- /wp:innerBlock --> <!-- /wp:outerBlock --> ``` The way this gets parsed leaves us in a quandary: we cannot reconstruct the original `post_content` after parsing because we lose the origin location information for each inner block since they are only passed as an array of inner blocks. ```json { "blockName": "core/outerBlock", "attrs": {}, "innerBlocks": [ { "blockName": "core/voidInnerBlock", "attrs": {}, "innerBlocks": [], "innerHTML": "" }, { "blockName": "core/innerBlock", "attrs": {}, "innerBlocks": [], "innerHTML": "\nwith its own content.\n" } ], "innerHTML": "\nCheck out my\n\nand my other\n\n" } ``` At this point we have parsed the blocks and prepared them for attaching into the JavaScript block code that interprets them but we have lost our reverse transformation. In this PR I'd like to introduce a new mechanism which shouldn't break existing functionality but which will enable us to go back and forth isomorphically between the `post_content` and first stage of parsing. If we can tear apart a Gutenberg post and reassemble then it will let us to structurally-informed processing of the posts without needing to be aware of all the block JavaScript. The proposed mechanism is a new property as a **list of HTML fragments with `null` values interspersed between those fragments where the blocks were found**. ```json { "blockName": "core/outerBlock", "attrs": {}, "innerBlocks": [ { "blockName": "core/voidInnerBlock", "attrs": {}, "innerBlocks": [], "blockMarkers": [], "innerHTML": "" }, { "blockName": "core/innerBlock", "attrs": {}, "innerBlocks": [], "blockMarkers": [], "innerHTML": "\nwith its own content.\n" } ], "innerHTML": "\nCheck out my\n\nand my other\n\n", "innerContent": [ "\nCheck out my\n", null, "\n and my other\n", null, "\n" ], } ``` Doing this allows us to replace those `null` values with their associated block (sequentially) from `innerBlocks`. ## Questions - Why not use a string token instead of an array? - See #11309. The fundamental problem with the token is that it could be valid content input from a person and so there's a probability that we would fail to split the content accurately. - Why add the `null` instead of leaving basic array splits like `[ 'before', 'after' ]`? - By inspection we can see that without an explicit marker we don't know if the block came before or after or between array elements. We could add empty strings `''` and say that blocks exist only _between_ array elements but the parser code would have to be more complicated to make sure we appropriately add those empty strings. The empty strings are a bit odd anyway. - Why add a new property? - Code already depends on `innerHTML` and `innerBlocks`; I don't want to break any existing behaviors and adding is less risky than changing.
@dmsnell thank you for the reference. I can see where your solution will lead but wouldn't it be easier to first render the sub HTML content and then passing it's content to the upper levels? Example: With your solution if you render World you would have to manually render the house and then make a recursive function to render table as in table could be another block an so on. What if the InnerBlocks had an onChange function which would return the content. This content is allready rendered and doesen't has to be checked for not rendered content as it is already done by it's predecessor (for example table). So your js code for World could look like this:
@chrisvanpatten and @jorgefilipecosta #7785 #11271 #10745 #6751 |
@NoelElias in #10108 I'm exploring a filtering API but you can see there that the inner blocks are already accessible to parent blocks in PHP as rendered HTML. I think there are two distinct ways we might want to process a block in PHP: before it's turned into HTML - "structural filtering"; after it's turned into HTML. For example, maybe I want to filter out any inner blocks of the type Anyway, I'd love to have you share your input in #10108, or at least the PHP-specific bits. There are some trivial things we can do like pass the array of rendered inner blocks to the |
@dmsnell I think this solution works for editing the innerBlock although registering a callback function inside This feature will be important but I still think, that having access to the rendered inner blocks inside render_callback is so much more important right now. Without it people will, for example, start hard coding their headings inside their blocks instead using the heading block provided. Also with your solution, passing the rendered inner blocks to the |
If I am following correctly, the update in https://core.trac.wordpress.org/ticket/45451 to add a filter to override block attributes solves the problems raised here (and noting that update should ship with WordPress 5.1). @manake, if that is not correct, would you mind please leaving me a comment to let me know? |
And so how do you use it?... |
@Tofandel It is exposed as https://developer.wordpress.org/reference/hooks/render_block_data/ Example: <?php
add_filter( 'render_block', function( $block_content, $block ) {
var_export( $block['innerBlocks'] );
return $block_content;
}, 10, 2 ); |
Where are |
@rodrigodagostino Those are the arguments passed to the filter callback. Make sure you include the fourth argument of https://developer.wordpress.org/reference/functions/add_filter/ |
@aduth yes, I understand those are the arguments I need to supply, but where am I supposed to get those from inside my render function? |
The inner blocks are not currently exposed on Instead, you can use the above filter and test whether |
Thanks for your efforts, @aduth , I still do not really understand how to use that filter. I might take a look to it later. |
Regardless of this perhaps being an old thread, it still came up high in google for a search I performed to find out how to output InnerBlocks in PHP, and there isn't much else in the way of info on how to do this. So I wanted to share how I got it working... In your php file for the block, you will have a function
Hope this helps anyone who is slightly lost. |
@flywolfcreative or anyone else:
and:
wordpress gives us this for block.js https://developer.wordpress.org/block-editor/tutorials/block-tutorial/nested-blocks-inner-blocks/:
how do I modify block.js (I assume this is where my problem is). I have tried various combinations of ServerSideRender and save : ... return null; thanks |
@flywolfcreative |
@debojyotighosh this is what works for me to use InnerBlocks content and render it using PHP (server-side) In your registerBlockType JS (focus on the save property): // JavaScript block register file
registerBlockType(block.name, {
title: block.title,
description: block.desc,
icon: block.icon,
parent: block.parentName,
category: block.categ,
attributes: block.attrs,
edit: () => {
return block.edit;
},
save: () => {
if(!block.usesInner)
return null;
else {
return <InnerBlocks.Content />
}
}
}); You can return null in the save function because your block will be rendered server-side (using PHP). However, when you're using InnerBlocks, the InnerBlocks.Content has to be returned, otherwise it will not be accessible to the PHP rendering function. Then, in the rendering function, you must use the following: // PHP block render file
function render_block($attributes, $content) {
// Normal block attributes
$title = $attributes['title'];
$subtitle = $attributes['subtitle'];
ob_start(); // Start HTML buffering
?>
<section>
<div class="container">
<h2>
<?php echo $title; ?>
</h2>
<h4>
<?php echo $subtitle; ?>
</h4>
<div class="content">
<?php echo $content; ?>
</div>
</div>
</section>
<?php
$output = ob_get_contents(); // collect buffered contents
ob_end_clean(); // Stop HTML buffering
return $output; // Render contents
} |
How can I access the attributes of a block within InnerBlocks? Let's say contains a |
Hello, Does anyone have an answer to the last question from @vladoa ? I'm trying to access the attributes from the innerblocks and can't find a way to do it. |
If you can't find any reference to your parent block, you could maybe get the current post content, use parse_blocks to get the whole block structure as an nested array, search for your block id and go from there ... |
Hi @jjarolim, |
Hi @jjarolim, I tried accessing the content via the $content variable and via get_the_content(). In both cases I don't see the attributes. This is my callback function:
This is was the output
|
What do you get via parse_blocks( get_the_content() ) ? You should get a iterable array with all blocks of the page incl. according attributes? |
Hi, @jjarolim thank you for your idea, sorry for the delayed response, I had problems with my laptop. I tried the following: Output is as follows: ' (length=2) ' (length=2) ' (length=2) ' (length=2) ' (length=353)
1 => null
2 => string ' So I don't think the attributes are being stored separately and I can't understand why. Steve |
This would be the easier way to access the innerblocks data in the block PHP render:
Btw, I created a full guide here: https://jeffreycarandang.com/how-to-access-innerblocks-attributes-within-the-parent-block-on-the-wordpress-gutenberg-editor/. Thanks! |
An example request regarding this documentation page: https://github.com/WordPress/gutenberg/tree/master/editor/components/inner-blocks
Similar example:
https://gist.github.com/mattheu/7cf235b4f932de891bc21cb5f3ff3de6
The text was updated successfully, but these errors were encountered: