Get the contents of a block instead of displaying it?
Permalink 1 user found helpful
I've been trying to find a way of returning the contents of a block (fully rendered) instead of having it instantly pushed out to the browser (using $b->display()).
It seems that there is no way to do this? I tried using output buffering to surround the call to $b->display() but it seems to still cause the output to be displayed in the browser.
I'm currently using the fact that my block is a content block and I can access the content via $b->getInstance()->getContent(), however this obviously only works for the content block type and I would prefer something generic that works for any block type.
Is there any other/better way of getting the content of a block in to a variable (I want to modify the content on the fly... in this particular case, using strip_tags() on it)?
It seems that there is no way to do this? I tried using output buffering to surround the call to $b->display() but it seems to still cause the output to be displayed in the browser.
I'm currently using the fact that my block is a content block and I can access the content via $b->getInstance()->getContent(), however this obviously only works for the content block type and I would prefer something generic that works for any block type.
Is there any other/better way of getting the content of a block in to a variable (I want to modify the content on the fly... in this particular case, using strip_tags() on it)?
That code still just *displays* the contents. To give you a slightly better idea of what I'm trying to do, this is what I have right now:
My "workaround" is where I assign a value to $html. What I would have preferred to be able to do was:
Where calling $block->display() would *return* the contents, instead of display it. Instead, there seems like there is no method (defined in the Block class or any inherited classes) of properly accessing the contents of a block, which is exactly what I require.
Creating a template for the block type is one method, however again that affects *only* that specific block type, and on top of that it's not a very "theme portable" method.
$a = new Area('Main'); if ($c->isEditMode()) { $a->display($c); } else { $b = $a->getAreaBlocksArray($c); foreach ($b as $i => $block) { $html = strip_tags($block->getInstance()->getContent()); echo '<div class="div-' . $i . ($i ? '">' : ' active">') . $html . '</div>'; } }
My "workaround" is where I assign a value to $html. What I would have preferred to be able to do was:
$html = strip_tags($block->display());
Where calling $block->display() would *return* the contents, instead of display it. Instead, there seems like there is no method (defined in the Block class or any inherited classes) of properly accessing the contents of a block, which is exactly what I require.
Creating a template for the block type is one method, however again that affects *only* that specific block type, and on top of that it's not a very "theme portable" method.
A quick hint, you can use ob_start to capture output.
http://php.net/manual/en/function.ob-start.php...
http://php.net/manual/en/function.ob-start.php...
<?php function callback($buffer) { // replace all the apples with oranges return (str_replace("apples", "oranges", $buffer)); } ob_start("callback"); ?> <html> <body> <p>It's like comparing apples to oranges.</p> </body> </html> <?php ob_end_flush();
Viewing 15 lines of 16 lines. View entire code block.
Yes, I actually mentioned I had tried that in my original post. You did almost the same thing I did, which was use ob_end_flush() (which in your example doesn't really help); I had used ob_get_flush().
I partially blame the PHP documentation for some reason not "recommending" ob_get_clean() when looking at ob_get_flush(). I was sure that a function should exist (in output buffering) to allow me to retrieve all output and *not* display it, but for whatever reason I totally missed seeing ob_get_clean().
Once I found ob_get_clean() I was able to do what I wanted:
I partially blame the PHP documentation for some reason not "recommending" ob_get_clean() when looking at ob_get_flush(). I was sure that a function should exist (in output buffering) to allow me to retrieve all output and *not* display it, but for whatever reason I totally missed seeing ob_get_clean().
Once I found ob_get_clean() I was able to do what I wanted:
$a = new Area('Main'); if ($c->isEditMode()) { $a->display($c); } else { $b = $a->getAreaBlocksArray($c); foreach ($b as $i => $block) { ob_start(); $tab->display(); $html = strip_tags(ob_get_clean()); echo '<div class="div-' . $i . ($i ? '">' : ' active">') . $html . '</div>'; } }
Thanks for this, really helpful!
Hi please can you help me out?
am trying to get back the html of a global area but i must be doing it wrong:
$a = new GlobalArea ('major module description ');
$b = $a->getAreaBlocksArray($c);
foreach ($b as $i => $block) {
ob_start();
$tab->display();
$html = strip_tags(ob_get_clean());
echo $html;
}
please can you tell me what i am missing here?
am trying to get back the html of a global area but i must be doing it wrong:
$a = new GlobalArea ('major module description ');
$b = $a->getAreaBlocksArray($c);
foreach ($b as $i => $block) {
ob_start();
$tab->display();
$html = strip_tags(ob_get_clean());
echo $html;
}
please can you tell me what i am missing here?
Hey! I was trying to do the same. Were you ever able to figure it out?
Thanks!
Thanks!
Actually, I think I just figured this out. Not sure if this helps you any, but Global Areas are kind of like Stacks. I just displayed the Global Area like this.....
Hope that helps you!
$block = Stack::getByName('Reserve Now Header'); if( is_object($block) ) $block->display();
Hope that helps you!
Enlil has a block in the prb that does that, so a global area can also be displayed as if it were a stack.
not as such but maybesome one here can help us? hehe.
i did a workaround though using jquery to update the blocks content. e.g. instead of editing the blocks html before its pushed to the screen... just update the html after page load
i did a workaround though using jquery to update the blocks content. e.g. instead of editing the blocks html before its pushed to the screen... just update the html after page load
For the php solution you need to capture and end the output buffer. Also you probably need to call ->display() on the block object (I have not checked the api for that)
sooo if i needed to do a preg_replace on a blocks html before pushing it to the screen would the code look like this? :
$block = Stack::getByName('my block'); if( is_object($block) ) $html = $block->display(); // am doing this in a page list block so am putting the page list parts into my link here. $link = "<a href=\"{$url}\" target=\"{$target}\">{$title}</a>"; // Replace the inside contents of the <h4> with the link. $html = preg_replace("@(<h4 class=\"reusable-heading\">)([^<]+)(</h4>)@","\\1{$link}\\3",$html);
You still need to capture the block output. display() will output to std out, not return a string.
For capturing the output buffer, see
http://uk3.php.net/manual/en/ref.outcontrol.php...
I am unclear what your ultimate objective is. If all you are doing is adding links to headings you may be able to use my Magic Linkify addon with no need to write php.
For capturing the output buffer, see
http://uk3.php.net/manual/en/ref.outcontrol.php...
I am unclear what your ultimate objective is. If all you are doing is adding links to headings you may be able to use my Magic Linkify addon with no need to write php.
For a page list block, have a look at Page List Teasers by jordanlev. May be a simpler starting point.
hi John yes i am getting a pages block out within a page list. the block was the container and the url / link was getting out put above the block so i wanted to combine them by adding the link with the blocks html.
i was using Teasers but it doesn't support global blocks.
i really needed to make it work with global blocks so i just got the stock page list view and output my global block within the loop.
i make my global blocks have there pages collection id appended to there handle so i just asked the page list what collection id each page has in the loop and put that id in the handle to get the correct global bock back.
i do this because i have a child page that my client can edit that will affect all the blocks in the parent pages.
basically am making site that has lessons with that have modules and then subjects above them. all the blocks on the subject and modules pages can be edit in on place with in each drop down / subject.
i was using Teasers but it doesn't support global blocks.
i really needed to make it work with global blocks so i just got the stock page list view and output my global block within the loop.
i make my global blocks have there pages collection id appended to there handle so i just asked the page list what collection id each page has in the loop and put that id in the handle to get the correct global bock back.
$myLessonId = $page->getCollectionID(); $a = new GlobalArea ('major module description '. $myLessonId .''); $a->display($c);
i do this because i have a child page that my client can edit that will affect all the blocks in the parent pages.
basically am making site that has lessons with that have modules and then subjects above them. all the blocks on the subject and modules pages can be edit in on place with in each drop down / subject.
I could be wrong, but my hunch is that every time you update a block, you will be polluting the database with a new global area name (and there is no garbage collection on area names). After a bunch of updates, anything that lists or selects stacks and global areas could become unmanageable.
ye the handles dont update them selves.
if the user made a new module by adding a page with that page type then a now global block is created with the modules collection id
then this modules block with its unique id will be out put in the page lists above the module page.
if the user made a new module by adding a page with that page type then a now global block is created with the modules collection id
then this modules block with its unique id will be out put in the page lists above the module page.
i needed the blocks to be global as i wanted the user to have access to the modules description block and subject block from the lessons page that is below the modules.
this allows the user to update everything from the lessons pages.
this allows the user to update everything from the lessons pages.
You can then modify or display the output.
Another solution is to modify the block template, copy the default template to /block/content/templates/mytemplate.php, you can then edit your custom template and assign it to the block, using Concrete5s interface.