1

I am trying to have a header with a different image for each page of my site. I believe I should be creating a block. I don't want to create x blocks for x pages, and I prefer to do it programmatically.

So I developped a block using in SubheaderBlock.php.

/**
 * Provides a 'SLS Block' Block
 *
 * @Block(
 *   id = "subheader",
 *   admin_label = @Translation("slssubheader"),
 *   category = "custom",
 * )
 */

namespace Drupal\subheader\Plugin\Block;

use Drupal\Core\Block\BlockBase;

class SubheaderBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() { 
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node) {
      $nid = $node->id();
    }

    return array(
      '#title' => '',
      '#description' => '',
      '#nid' => $nid,
    );
  }
}

Then, I can use the node ID in the Twig template and change the picture accordingly. The node ID is well passed to the Twig template, but it is cached! So, whenever the page change, {{ #nid }} outputs the same ID.

I have also tried to change Twig template suggestion and have a Twig template for each page, but still there are same caching problem.

The code below is probably not the perfect one.

/**
* @file
* Code for the example module.
*/

/**
 * Theme hook
 */
function subheader_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
    $twig = 0;
    // change the suggestion only for the block_id 'subheader'
    if(isset($variables['elements']['#plugin_id'])){
        if  ($variables['elements']['#plugin_id']=== "subheader"){
            // give the twig template the same ID as the NID 
            $node = \Drupal::routeMatch()->getParameter('node');
                if ($node) {
                $twig = $node->id();
                }
    // suggestion pattern is 'block__subheaderID 
    $suggestions[] = $hook . '__' .'subheader'.$twig;
}}
}

A

  • Provide route cache context to your block's render array or node_list cache tag. – user21641 Feb 12 '16 at 8:59
  • Thanks a lot for your help. That was the lead I was missing... I will publish my code once I eventually make it work :-) – 123pierre Feb 12 '16 at 12:58
  • You could also create a block view in Views UI to display a single image result if the images are stored in the database as a field somewhere. – mradcliffe Feb 12 '16 at 14:01
0

After some many headache... I believe I got what I wanted, thanks to Ivan.

SubheaderBlock.php

<?php
/**
 * Provides a 'Subheader' Block
 *
 * @Block(
 *   id = "slssubheader",
 *   admin_label = @Translation("slssubheader"),
 * )
 */

namespace Drupal\subheader\Plugin\Block;
use Drupal\Core\Block\BlockBase;

class SubheaderBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {

   // get the node id if exist
   $node = \Drupal::routeMatch()->getParameter('node');
   $nid = $node ? $node->id() : 0 ;


   $outpout['id'] = array(
           '#markup' => $nid,
           '#cache'=>[
                 'contexts' => ['url:pager_id' ],
                 ]

       );

    return $outpout;
  }
}
?>

I get the id in twig with

{{ content.id }}

I checked with a a random number rand(1,100) it works perfect. There is one different cache per nid.

althought it works, I am not sure about the best practice for #markup and url:pager_id

  • I am stuck with another problem: Twig can display {{ content.id }} but the {% if content.id == xxx %} does not work. Why? It works with {% if content.id['#markup'] %} though.... Believe it or not, it works only if I display {{ content.id }} somewhere in my twig code. I soon as I remove this {{ content.id }} from the code, drupal will cache it anyway.... I believe it is getting too complicated for my humble knowledge, i will try to extend page.html.twig, this sound more reasonable. If some expert reads me, I am quite curious to understand this behaviour... (hope I have been clear, not easy) – 123pierre Feb 15 '16 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.