ブロックをプログラムで表示するにはどうすればよいですか?


33

Drupal 8 beta-14を使用してサイトを開発しています。さまざまな用語のビューブロックを作成しましたが、コードを使用して表示したいと思います。プログラムで表示するにはどうすればよいですか?以前はこのコードを使用してDrupal 7で実行していましたが、Drupal 8については混乱しています。

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

回答:


69

ブロックには2つのタイプがあり、2つのレンダリング方法は少し異なります。

コンテンツブロック

コンテンツブロックは、インターフェイスで作成するブロックです。これらは、フィールドなどを備えたノード構成可能なデータ構造によく似ています。これらのいずれかをレンダリングする場合、エンティティで通常行うことを実行し、それらをロードしてビュービルダーでレンダリングできます。

$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;

構成エンティティ

2つのタイプで共有されるのはブロックです。リージョンに挿入すると、ブロックのすべての設定を持つ構成エンティティが作成されます。場合によっては、構成エンティティの処理がより便利になります。同じブロックを異なる構成の複数の領域に配置できるため、ブロック構成エンティティを使用すると、さらに注意が必要になります。良い点は、特定の構成でブロックをレンダリングしたいということです。悪いことは、インターフェイスをいじることで構成IDを変更できるため、ユーザーにブロックインターフェイスを使用させた後にコードが機能しなくなる可能性があることです。

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

2
質問は、ブロック構成エンティティ(事前構成されたブロック配置)のレンダリングに関するものか、ハードコードされた構成を持つブロックプラグインに関するものかを指定しません。7.xにはその違いが存在しないため、これは理にかなっています。これは、他のものが実際に特定のテーマと地域に配置する必要がある特定のブロックを必要とするため、より柔軟です。ただし、決して手動で作成しないでください。プラグインIDを使用して、ブロックプラグインマネージャーのcreateInstance()メソッドを使用します。ここで、$ configuration配列を提供することもできます...
Berdir

2
また、ブロックのアクセスがそのブロックによる特定の許可などに制限されている場合に、最初にaccess()メソッドを呼び出すことを検討することもできます。それについて少し答えを改善できますか?その後、有用なリソースになることができます:)
Berdir

1
@Berdirしばらく経ちましたが、ようやく答えを改善することになりました。さまざまなキャッシュがすべて実行されているため、プラグインを直接使用することは、おそらく限られた状況でのみ有用です。
googletorp

4
ブロックプラグインマネージャーcreateInstance()を使用する場合の欠点は、結果のレンダー配列がブロックテーマを実行しないため、たとえばblock-.blockname.twig.htmlを使用できないことです。別の方法は、テーマのブロックを作成しますが、無効のままにして、コードで次のようにします: `` `$ block = \ Drupal \ block \ Entity \ Block :: load( 'myblock'); $ build = \ Drupal :: entityManager()-> getViewBuilder( 'block')-> view($ block); `` `
-joachim

1
いや-もう一つのウサギの穴。コンテンツブロックの白い画面のコード(悪名高い「Webサイトで予期しないエラーが発生しました。しばらくしてからもう一度お試しください。」)私はシステムブロックを試みているので真実ではありません-drupalの力で動くもの)。
sea26.2

16

前処理を使用してテンプレート内のブロックのみを表示するための最良の方法は

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

そして、page.html.twigorまたはnode.html.twigorで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、レンダー配列にプロパティに関するドキュメントが見つかりません。文書化されている場所を知っていますか?
エリア

理由はわかりませんが、\Drupal\block\Entity\Block::load常にブロックを返すわけではありません。ロードしたブロックがブロックレイアウトのビュー内に配置されている場合にのみ、何かを返します。配置されていない場合は、nullを返します。
アーサーAttout

この回答は、使用するために更新する必要があります\Drupal::entityTypeManager()->getViewBuilder('block')->view($block);
ライアンハートマン

6

トップの答えに加えて...ビューからブロックをレンダリングしたい場合、少し違ったやり方をしなければならないかもしれません。

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

(表示名例-> block_1)

Twigに渡すので、レンダリングする必要はありません(レンダリングサービスを使用)。

そのため、twigに変数として渡すだけです(この例では、コントローラーの戻り値)。

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()でした。
レイマンクス

1
重要なのは、少なくとも「無効なブロック」領域にブロックを配置する必要があることです。または他のアクティブな領域。
レイマンス16

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

基本的に、レンダリングには2つのタイプがあります。

  1. レイアウトにブロックの既存のインスタンスがある場合。ブロックは、プリプロセスを使用して小枝にレンダリングできます

    $ block = 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($ 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のDrupalに廃止され
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

あなたが正しい。これは推奨される最も柔軟なソリューションではありません。
レオランドタン

リンクが
無効
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.