프로그래밍 방식으로 블록을 표시하려면 어떻게해야합니까?


33

Drupal 8 베타 -14를 사용하여 사이트를 개발 중입니다. 다른 용어의 뷰 블록을 만들었으며 코드를 사용하여 표시하고 싶습니다. 프로그래밍 방식으로 표시하려면 어떻게해야합니까? 이 코드를 사용하여 Drupal 7에서 사용했지만 Drupal 8에 대해 혼란 스럽습니다.

$block = module_invoke('block', 'block_view', '4');
$text_block = render($block['content']);

답변:


69

두 가지 유형의 블록이 있으며 두 가지를 렌더링하는 방법은 약간 다릅니다.

콘텐츠 블록

컨텐츠 블록은 인터페이스에서 작성하는 블록입니다. 이들은 필드 등을 포함하여 노드 구성 가능한 데이터 구조와 매우 유사합니다.이 중 하나를 렌더링하려면 엔티티로 일반적으로 수행하는 작업을 수행하고로드 한 후 뷰 빌더로 렌더링 할 수 있습니다.

$bid = ??? // Get the block id through config, SQL or some other means
$block = \Drupal\block_content\Entity\BlockContent::load($bid);
$render = \Drupal::entityTypeManager()->
  getViewBuilder('block_content')->view($block);
return $render;

플러그인 블록

블록은 다양한 모듈에서 정의 된 플러그인 일 수도 있습니다. 예를 들어 이동 경로 블록이 있습니다. 이를 렌더링하려면 블록 플러그인 관리자를 사용해야합니다.

$block_manager = \Drupal::service('plugin.manager.block');
// You can hard code configuration or you load from settings.
$config = [];
$plugin_block = $block_manager->createInstance('system_breadcrumb_block', $config);
// Some blocks might implement access check.
$access_result = $plugin_block->access(\Drupal::currentUser());
// Return empty render array if user doesn't have access.
// $access_result can be boolean or an AccessResult class
if (is_object($access_result) && $access_result->isForbidden() || is_bool($access_result) && !$access_result) {
  // You might need to add some cache tags/contexts.
  return [];
}
$render = $plugin_block->build();
// In some cases, you need to add the cache tags/context depending on
// the block implemention. As it's possible to add the cache tags and
// contexts in the render method and in ::getCacheTags and 
// ::getCacheContexts methods.
return $render;

구성 엔티티

두 유형이 공유하는 블록은 영역에 일단 삽입하면 블록에 대한 모든 설정이 포함 된 구성 엔티티를 생성한다는 것입니다. 어떤 경우에는 구성 엔티티를 처리하는 것이 더 유용 할 것입니다. 구성이 다른 여러 영역에 동일한 블록을 배치 할 수 있으므로 블록 구성 엔터티를 사용하면 더 까다로울 수 있습니다. 좋은 점은 특정 구성으로 블록을 렌더링 할 수 있다는 것입니다. 나쁜 점은 인터페이스를 엉망으로 구성 ID를 변경할 수 있으므로 사용자가 블록 인터페이스를 사용하도록 한 후 코드가 작동하지 않을 수 있다는 것입니다.

$block = \Drupal\block\Entity\Block::load('config.id');
$render = \Drupal::entityTypeManager()
  ->getViewBuilder('block')
  ->view($block);
return $render;

2
이 질문은 블록 구성 엔터티 (사전 구성된 블록 배치) 또는 하드 코딩 된 구성으로 블록 플러그인을 렌더링하는지 여부를 지정하지 않습니다. 그 차이는 7.x에 없기 때문에 의미가 있습니다. 다른 하나는 실제로 특정 테마와 영역에 배치해야하는 특정 블록이 필요하기 때문에 더 유연합니다. 그러나 손으로 직접 만들면 안됩니다. 당신은 또한 $ 구성 배열을 제공 할 수있는 플러그인 ID, ...와 그의 블록 플러그인 관리자의으로 createInstance () 메소드를 사용하여
Berdir

2
또한 블록 액세스가 해당 블록의 특정 권한으로 제한되는 경우 access () 메서드를 먼저 호출하는 것이 좋습니다. 그것에 대한 답변을 약간 향상시킬 수 있습니까? 유용한 자원이 될 수 있습니다 :)
Berdir

1
@ Berdir 오랜 시간이 지났지 만 마침내 대답을 개선하기 위해 왔습니다. 모든 다양한 캐싱이 진행되는 동안 플러그인을 직접 사용하는 것은 제한된 상황에서만 유용 할 것입니다.
googletorp

4
블록 플러그인 관리자 createInstance () 사용의 단점은 결과 렌더링 배열이 블록 테마를 통해 실행되지 않으므로 블록 이름 (예 : blockname.twig.html)을 사용할 수 없다는 것입니다. 대안은 당신의 테마를위한 블록을 생성하는 것이지만 비활성화 된 상태로두고 코드에서 :```$ block = \ Drupal \ block \ Entity \ Block :: load ( 'myblock'); $ build = \ Drupal :: entityManager ()-> getViewBuilder ( 'block')-> view ($ block); ```
joachim

1
아니-또 다른 토끼 구멍. 콘텐츠 차단 흰색 화면의 코드 (유명하지 않은 "웹 사이트에 예기치 않은 오류가 발생했습니다. 나중에 다시 시도하십시오.") 두 번째가 가까워 지지만 블록이 누락되었거나 무언가에 대한 암호 메시지가 표시됩니다. 내가 시스템 블록을 시도하고 있기 때문에 사실이 아닙니다-drupal에 의해 구동됩니다).
sea26.2

16

사전 프로세스로 템플릿에 블록 만 표시하는 가장 좋은 방법은

$block = \Drupal\block\Entity\Block::load('my_block_id');
$variables['My_region'] = \Drupal::entityManager()
          ->getViewBuilder('block')
          ->view($block);

그리고 당신에 page.html.twignode.html.twig또는 xxx.html.twig같은 당신의 변수 My_region을 사용합니다 :

{% if page.My_region %}
    {{ page.My_region }}
{% endif %}

그리고 렌더링 가능한 배열 (커스텀 모듈)에서 content ()의 컨트롤러 커스텀으로 :

public function content() {
    $block = \Drupal\block\Entity\Block::load('my_block_id');
    $block_content = \Drupal::entityManager()
      ->getViewBuilder('block')
      ->view($block);

          return array(
        '#type' => 'container',
        '#attributes' => array(
          'class' => array("Myclass"),
        ),
        "element-content" => $block_content,
        '#weight' => 0,
      );
}

사용 drupal_renderDrupal은 이미 D8에서 렌더링을 가정하고 있기 때문에 유용하지 않습니다 . \Drupal::service('renderer')->renderRoot()대신 사용해야 합니다.

약간 무겁고 최대 영역 시스템을 사용하는 것이 좋으며 사전 프로세스에서로드 블록을 추가하지 않습니다. 모듈에서 컨트롤러를 사용하는 경우 정당한 사용으로 보입니다.


이 컨트롤러 구현은 내가 찾던 것입니다. 감사!
Mrweiner

내가 다루고있는 비슷한 사용 사례에 대한이 컨트롤러 구현에 관심이 있습니다. 그러나 element-content렌더 배열에서 속성에 대한 문서를 찾을 수 없습니다 . 어디에 기록되어 있는지 알고 있습니까?
Eria

이유를 모르지만 \Drupal\block\Entity\Block::load항상 블록을 반환하지는 않습니다. 내가로드 한 블록이 블록 레이아웃 의 뷰 내에 배치 된 경우에만 무언가를 반환 합니다 . 배치하지 않으면 null을 반환합니다.
Arthur Attout

이 답변은 다음과 같이 사용되도록 업데이트되어야합니다\Drupal::entityTypeManager()->getViewBuilder('block')->view($block);
Ryan Hartman

6

상위 답변 외에도 ... 뷰에서 블록을 렌더링하려면 약간 다르게 처리해야 할 수도 있습니다.

$view = views_embed_view('my_view_name', 'my_display_name');

(표시 이름 예 :-> block_1)

이를 나뭇 가지에 전달할 것이므로, 렌더링 서비스를 사용하여 렌더링 할 필요가 없습니다.

따라서 변수를 나뭇 가지에 전달할 수 있습니다 (이 예에서는 Controller의 반환).

return [
  ['description' => [
    '#theme' => 'your_theme_hook',
    '#your_variable => $view
  ]
]

모듈에서 변수에 대한 hook_theme ()이 필요합니다.

function hook_theme($existing, $type, $theme, $path) {
  return array(
    'your_theme_hook' => array(
      'variables' => [
        'your_variable' => NULL,
      ]
    )
  )
}

마지막으로 나뭇 가지 템플릿에서 :

{{ your_variable }}

5

사용자 정의 블록의 HTML을 가져 와서 다음을 사용했습니다.

$con = \Drupal\block\BlockViewBuilder::lazyBuilder('bartik_search', 'full');
$d   = \Drupal::service('renderer')->renderPlain($con);

print $d->__toString();

1
렌더 배열에 추가해야했고 거기없이 작동했습니다 __toString().
leymannx

1
적어도 블록은 "비활성화 된 블록"영역에 배치해야합니다. 또는 다른 활성 지역.
leymannx

1
// You need a block_id! to get it just click configure in the desire block and you'll get url like this /admin/structure/block/manage/bartik_search   the last part of the parameter is the block id
$block = \Drupal\block\Entity\Block::load('bartik_search');
$block_content = \Drupal::entityManager()
  ->getViewBuilder('block')
  ->view($block);

return array('#markup' => \Drupal::service('renderer')->renderRoot($block_content));

가능 drupal_render하면 렌더링 서비스를 사용하지 않아야 합니다. drupal_render사용되지 않지만 렌더링 된 내용으로 배열을 렌더링하는 것은 꽤 나쁩니다. $block_content대신 반환해야 합니다. 렌더링 배열은 실제 렌더링 전에 변경 될 수 있으며 Drupal이 렌더링을 가능한 한 가능한대로 또는 스스로 수행하도록해야합니다.
googletorp

이것은 블록 레이아웃을 통해 블록이 이미 페이지에 배치 된 경우에만 작동합니다.
hugronaphor

1

기본적으로 두 가지 유형의 렌더가 있습니다.

  1. 레이아웃에 기존 블록 인스턴스가있는 경우 사전 프로세스를 사용하여 블록을 나뭇 가지로 렌더링 할 수 있습니다.

    $ block = 블록 :: load ( 'BLOCK_ID'); $ variables [ 'social_links'] = \ Drupal :: entityTypeManager ()-> getViewBuilder ( 'block')-> view ($ block);

  2. 블록에 대한 인스턴스 또는 구성이 없습니다. 그런 다음 전 처리기에서 인스턴스를 생성하고 블록을 빌드 한 다음 렌더링해야합니다.

    $ block_manager = \ Drupal :: service ( 'plugin.manager.block'); $ config = []; $ plugin_block = $ block_manager-> createInstance ( 'farmjournal_social_sharing', $ config); $ render = $ plugin_block-> build (); $ variables [ 'farmjournal_social_sharing'] = 렌더링 ($ render);


0

이것은 플러그인 블록에서 작동하는 것 같습니다 ..

$block = \Drupal\block\Entity\Block::load('some_block_id_3');
  $pluin = $block->getPlugin();
  $build = $pluin->build();
  $build['#weight'] = 4;
  $form['block'] = $build;

-2

블록 출력을 얻습니다.

$block = \Drupal\block\Entity\Block::load ('my_bock_id');
$block_content = \Drupal::entityManager ()->
  getViewBuilder ('block')->
  view ($block);

그런 다음 다른 방법으로 출력을 반환 할 수 있습니다.

return array (
    '#type' => 'container',
    'element-content' => $block_content
);

또는:

return ['#markup' => \Drupal::service ('renderer')->render ($block_content)];

\Drupal::service ('renderer')->render ($block_content)으로 수행 할 수 있습니다 drupal_render ($block_content)그러나 후자는 8 드루팔에서 더 이상 사용되지 않습니다
olegiv

가능 drupal_render하면 렌더링 서비스를 사용하지 않아야 합니다. drupal_render사용되지 않지만 렌더링 된 내용으로 배열을 렌더링하는 것은 꽤 나쁩니다. $block_content대신 반환해야 합니다. 렌더링 배열은 실제 렌더링 전에 변경 될 수 있으며 Drupal이 렌더링을 가능한 한 가능한대로 또는 스스로 수행하도록해야합니다. 당신은 실제 렌더링 무의미하게하는, 다시 렌더링 할 필요를 반환
googletorp

-2

내 연구에 따르면 drupal 8에서 프로그래밍 방식으로 블록을 렌더링하는 방법 의 코드를 기반으로 할 수 있습니다 . 당신은 또한 변경할 수 있습니다

return array('#markup' => \Drupal::service('renderer')->renderRoot($block_content));

다음과 같이 간단한 것으로

$output .= \Drupal::service('renderer')->renderRoot($block_content);

예를 들어 페이지의 리턴 변수에 첨부하십시오.


가능 drupal_render하면 렌더링 서비스를 사용하지 않아야 합니다. drupal_render사용되지 않지만 렌더링 된 내용으로 배열을 렌더링하는 것은 꽤 나쁩니다. $block_content대신 반환해야 합니다. 렌더링 배열은 실제 렌더링 전에 변경 될 수 있으며 Drupal이 렌더링을 가능한 한 가능한대로 또는 스스로 수행하도록해야합니다.
googletorp

네가 옳아. 권장되는 가장 유연한 솔루션은 아닙니다.
Leolando Tan

귀하의 링크가 죽었습니다 "블록을 렌더링하는 방법 ..."
sea26.2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.