Score:-2

How do I show a block with a unique QR for each node?

th flag

There is requirement where I need to Place a Block on node where each block will be having the Unique QR code.

I created an hard-coded QR code block with the following code.

public function build() {
  $path = '';
  $directory = "public://Images/QrCodes/";
  \Drupal::service('file_system')->prepareDirectory($directory, \Drupal\Core\File\FileSystemInterface::CREATE_DIRECTORY);
  $qrName = 'myQrcode';
  $uri = $directory . 'QR'. '.png'; // Generates a png image.
    
  $path =  \Drupal::service('file_system')->realpath($uri);
    
  \PHPQRCode\QRcode::png("www.google.com", $path, 'L', 4, 2);
  
  $relative_file_url =  \Drupal::service('file_url_generator')
    ->generateAbsoluteString($uri); 
    
  $qr_image = "<img src='{$relative_file_url}'/>";
      
  return [
    '#markup' => $qr_image,
  ];
}

The only issue is that I am not able to add the block to nodes nor to make the QR code dynamic.

It means that Each node will have a unique QR Code Block.

How to create a dynamic block inside hook_preprocess_node ?

Please Help

leymannx avatar
ne flag
So this was the original task linked in the question https://github.com/Dineshkushwaha/sph-test/blob/main/README.md, and it looks a little bit as if you let others do your homework.
fr flag
You first need to understand what a block and a node are and how they differ from a page. You can't "place a block on a node". Blocks are placed on a *page*, as part of the page display; that page might or might not *also* display a node.
leymannx avatar
ne flag
And there's just a list of pull request with possible solutions. https://github.com/Dineshkushwaha/sph-test/pulls Maybe try to read and understand them first.
apaderno avatar
us flag
The answer to *How do I create a dynamic block inside `hook_preprocess_node()`?* is *You don't.* since `hook_preprocess_node()` isn't thought to create dynamic blocks.
Score:5
cn flag

This is the original description of the task (now removed from the question):

Build the following:

  • A Drupal content type to hold all their products
  • A Drupal block that can be placed on any product page. The block, when placed on any product page, automatically shows the currently displayed product's App Purchase Link as a QR code, that the site visitors can scan using their mobile.

You can use the current route to get the node and add a unique block for each node:

/src/Plugin/Block/ExampleBlock.php:

<?php

namespace Drupal\mymodule\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides an example block.
 *
 * @Block(
 *   id = "mymodule_example",
 *   admin_label = @Translation("Example"),
 *   category = @Translation("mymodule")
 * )
 */
class ExampleBlock extends BlockBase {

  public function build() {
  
    $build = [];

    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof \Drupal\node\NodeInterface) {
      // calculate $qr_image with $node
      $build = [
        '#markup' => $qr_image,
        '#cache' => ['tags' => $node->getCacheTags()],
      ];
    }

    $build['#cache']['contexts'] = ['route'];
    return $build;
  }
}

2. Version

Implementing the same block with a node context, as @leymann suggested:

/src/Plugin/Block/ExampleBlock.php:

<?php

namespace Drupal\mymodule\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides an example block.
 *
 * @Block(
 *   id = "mymodule_example",
 *   admin_label = @Translation("Example"),
 *   category = @Translation("mymodule"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node")
 *   }
 * )
 */
class ExampleBlock extends BlockBase {

  public function build() {
    $node = $this->getContextValue('node');
    // calculate $qr_image with $node
    return [
      '#markup' => $qr_image,
    ];
  }
  
}

The advantage, you don't need to take care about caching, the context does this automatically. The disadvantage, you need to make the block dependent on a context when placing it in the block layout. Drupal is not yet able to map a block context automatically. You could, for example, add a visibility for the content type, which is probably a good idea anyway.

th flag
But How do I add block on node ?
4uk4 avatar
cn flag
Place the block in the right sidebar, according to [your plan](https://drupal.stackexchange.com/questions/310719/how-do-i-show-a-block-with-a-unique-qr-for-each-node/310724?noredirect=1#comment395068_310721). When you then visit a node the block will be displayed, with the QR-Code for that node. On other pages the block is empty and will be hidden.
leymannx avatar
ne flag
(The node could be injected from context and \Drupal calls should be avoided. )
4uk4 avatar
cn flag
@leymannx, the context is a great idea and this removes any \Drupal calls, without DI ;-)
Jaypan avatar
de flag
You can also add the block in Layout Builder if you are using it.
Score:2
cn flag
  1. The simple answer is: if you don't want/can't use the https://www.drupal.org/project/twig_tweak - then just copy the code of the drupal_block Twig extension from that module to your own module.

  2. If that is not the case - just simply implement hook_preprocess_node and put your block build code there or load the block and send it to a node template via $variables.

  3. Use the layout builder module (in core) to place the blocks on the node pages.

cn flag
BTW, from your code I don't see how this connected to particular node.
th flag
I have searched a lot but not finding the way to place the block on nodes. Could you please help
th flag
found this https://stackoverflow.com/questions/43771500/using-preprocess-hook-on-specific-node-type-in-drupal-8..Trying now
cn flag
Just copy the content of your block `build()` method to node preprocess and get rid of the block.
cn flag
Added one more solution.
th flag
In problem statement, it is clearly mentioned that I have to make a use of Block and that block should be placed on right side bar, but thanks for your answers.
Score:1
fr flag

The Barcodes module https://www.drupal.org/project/barcodes provides a block displaying a barcode of any type, including QR code. This task is as simple as enabling the module then configuring the block to display what you want. No coding necessary. Barcodes supports tokens so you can dynamically encode and display a product ID, a node ID, or any other information in your barcode block.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.