Dynamic Block Weight in Drupal 8

drupal blocks

In such a time, i want to place blocks in sidebar region with the dynamic weight. It means the blocks should render in different position for each page request. I have searched and tried lots of method but unfortunately i can’t find proper method to do that. So i have decided to do that with some hacky way.

Drupal 8 is providing a hook to alter the region template_preprocess_region, it would prepares values to the theme_region. I have planned to use the hook to alter the block's position to be rendered in the region.

Adding the following codes in THEMENAME.theme file would solve the problems,

function themename_preprocess_region(&$variables) {
  if ($variables['region'] == 'sidebar_second') {
    $variables['elements'] = shuffle_assoc($variables['elements']);
    $content = '';
    foreach ($variables['elements'] as $key => $value) {
      if (is_array($variables['elements'][$key])) {
        $content .= \Drupal::service ('renderer')->render($value);
      }
    }
    $variables['content'] = array(
      '#markup' => $content,
    );
  }
}

function shuffle_assoc($list) {
  if (!is_array($list)) {
    return $list;
  }

  $keys = array_keys($list);
  shuffle($keys);
  $random = array();
  foreach ($keys as $key) {
    $random[$key] = $list[$key];
  }
  return $random;
}

It is working well in my site but i know it is the hacky way, not sure about the proper way to do that. If anyone of you know about this kindly share it in the comments :)