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


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.twig나 node.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.