Have you ever wondered how you can get a block to display smack down in the middle of your Body content? Say you write articles and these get displayed like normally in the Content region. You can add blocks to regions around it but only if your theme has them declared or if you did that yourself in the template of with Display Suite. And the cat is cute.
What you cannot so easily do is have a block displayed on each Article node in the middle of your Body. Not even with Display Suite. If you know a little .php
however, it is not so difficult. And of course if the node.tpl.php
file does not scare you.
This is what I did for my Article Content Type. I created a dedicated node.tpl.php
file for the Article Content Type by copying node.tpl.php
and renaming the new file node--article.tpl.php
. You can do this also for you Page Content Type and any other you may have - in the same naming style.
I searched for the following .php
line print render($content);
and commented it out. Note that this line outputs the Body field of all the Article nodes on your site. If you comment it out on your production website, none of your Article nodes will have any Body fields till you are finished with this entire process. So make sure you work first in your development environment, perform adequate testing there and then make all the changes at once.
Next, I added a new region to my theme called new-region
(Of course change the name to whatever you want).
The reason I did this is so that I can create a block of content in the Drupal UI and assign it to this region. This will in turn be called with .php
in the middle of the Article Body fields. So after this, I went back to my article--note.tpl.php
and declared a new variable ($added_string
) containing said call for the region:
$added_string = render(block_get_blocks_by_region('new-region'));
Next, I used a .php
command to break up the render version of the $content
variable (which holds the Body text). Seeing that this text is mostly a sequence of paragraphs, I broke it up at each paragraph and stored all the resulting pieces in the array named $content_array
:
$content_array = explode("<p>", render($content));
UPDATE: Here if you have more fields in your content type and you want to add your block in the middle of the body
field - which is expected to be simple html - you should explode
only the specific body
array element, like so:
$content_array = explode("<p>", render($content['body']));
OK, so what I wanted to do is have the block display roughly in the middle of the Body field. It is difficult to be precise given that you cannot break up the $content
variable exactly in the middle. The .php
command above, however, created an array with a number of elements (and since we used the paragraph as the separator) we can also deduce that $content_array
is now an array of all the paragraphs in the Body.
Now, we find out how many paragraphs it has and divide that number in 2 to figure out where we want to insert the block content (after how many paragraphs). For this you can also set a number of your own, but in my case I wanted the block to be more or less in the middle, no matter how long the Article content got:
$content_array_half_size = count($content_array) / 2;
The above command retrieved the half of the total number of items (paragraphs) in the array and stored that number in the variable called $content_array_half_size
. Next, I used another command to insert the region I wanted (now found in the variable $added_string
) into the Body array ($content_array
) placing it after the item that equals to the number representing half of the total items:
array_splice($content_array, $content_array_half_size, 0, $added_string);
And finally, I needed to recreate the string to be outputted as the Body field because currently $content_array
is an array which holds a number of paragraphs - with the block included in the middle:
$final_content = implode("<p>", $content_array);
As you notice, I used the same selector ("<p>"
) as criterion to implode the array elements. And now the $final_content
variable holds a big string with our Body and block in the middle of it. All we need to do is print it out:
print $final_content;
OK, so after saving this file and adding your block to that region in your Drupal administration interface, you can test. If you are satisfied, you can go ahead and implement these changes on your production site.
You could of course not use a block as a content holder to be placed in the middle of the Body. You can hardcode in the node--article.tpl.php
file the $added_string
to whatever you want. But using a block in a region gives you then the opportunity to always return to the Drupal UI to show/hide that block based on various dependencies: page, role, or even add more blocks to that region. Also, you can use the Context module to disable the region itself etc. And that is cool.
Hope this helps.
Daniel Sipos
Danny founded WEBOMELETTE in 2012 as a passion project, mostly writing about Drupal problems he faced day to day, as well as about new technologies and things that he thought other developers would find useful. Now he now manages a team of developers and designers, delivering quality products that make businesses successful.
Comments
preprocess node
Thank you, you're tutorial was of great help. I did however not use the template files but used template_preprocess_node(&$variables,$hook). You can use it in template.php or a custom module.
Instead of render($content), I update the body text in $variables['content']['body'][0]['#markup'] and made a switch command based on $variables['type']. Maybe not the nicest solution but it prevents multiple template files with php in it.
But for the ones who do not want to go into the code there is always your module. Thanks again.
In reply to preprocess node by Erik (not verified)
Yes,
Yes,
Check out my module Block Inject I wrote for this use case in the meantime :)
D
Hey, thank you so much for
Hey, thank you so much for this tutorial! I had to do exactly the same and already figured it could work something like this but your code definitely was a big time-saver. :)
Add a Block article
Could you ad an image of your node.tpl.php with the above code in it?
Thanks,
Mike
Yeah no clue. Any way to dumb
Yeah no clue. Any way to dumb it down??
How can we do this for a drupal 8 twig template
How can we do this for a drupal 8 twig template
Add new comment