Replacing the content in the custom block is often challenging. In Drupal 8, the best way to replace the content in the custom block programmatically is to use module_preprocess_block alter.
We have created a custom block and now we want to replace the value of the placeholder programmatically. For eg. On http://example.com/, we have created a custom block named “Test Block” for the home page. The body of the custom block contains the following code:
[java]
<div>
<div class="“content”">
<h5><a href="“{{link}}”">Test Block</a></h5> // {{link}} represents the placeholder
</div>
</div>
[/java]
Now we want to replace the value of placeholder ({{link}}) with a node page URL link programmatically. Here’s how to go about it:
Create an alter module by following the below steps:
Step 1- Create a test folder in the modules folder
Step 2- Create “test.info.yml” file that will have entire information about module such as name, type, package, version.
[java]
name: Test Block
description: ‘Module to replace the placeholder.’
package: Custom
type: module
core: 8.x
[/java]
Step 3- Create “test.routing.yml” file and add routing for this module
Step 4- Create “test.module” file which will contain the preprocess alter of the custom block. The custom block contains the placeholder
Step 5- Open the test.module file and add preprocess alter code as shown below:
[java]
use Drupal\Core\Block\BlockBase;
use Drupal\node\Entity\Node;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\field\Entity\FieldConfig;
/**
* function preprocess block for Test block
*/
function test_preprocess_block(&$variables)
{
if (isset($variables[‘content’][‘#block_content’]))
{
$content = $variables[‘content’][‘#block_content’];
if( method_exists($content,’id’) && $content->id() == ‘block_id’)
/*
* Block Id represents id of coressponding block which contains the placeholder.
*/
{
$body = $variables[‘content’][‘body’][0][‘#text’];
/*
* now you need to replace with placeholder by finding the dynamic link
*/
$query = \Drupal::entityQuery(‘node’);
$query->range(0, 1);
$result = $query->execute();
$nids = array_values($result);
if (isset($nids[0]))
{
$node_load = Node::load($nids[0]);
$options = array(‘absolute’=>TRUE);
$url = Url::fromRoute(‘entity.node.canonical’, [ ‘node’=>$nids[0] ], $options);
$Url = $url->toString();
$body=str_replace(‘{{link}}’,$Url,$body);
$variables[‘content’][‘body’][0][‘#text’] = $body;
}
}
}
}
[/java]
The Block Id and the placeholder are highlighted in the following image:

We hope you will able to now replace the content in your custom block easily following the above steps. In case if you have more queries about Drupal 8 custom blocks, feel free to share them in the comments below.
Thanks for useful trickes, I was searching for quite time but finally I was able to change content base on my requirement on the fly. By the way my question is can’t we do same with how to identify particular block using hook_block_alter which i try to used before this but it didn’t work.
Nice & usefull blog