Bagaimana saya bisa menampilkan blok secara terprogram?


33

Saya mengembangkan situs menggunakan Drupal 8 beta-14. Saya telah membuat blok tampilan istilah yang berbeda dan sekarang saya ingin menampilkannya menggunakan kode. Bagaimana saya bisa menampilkannya secara terprogram? Saya dulu melakukannya di Drupal 7 menggunakan kode ini, tetapi saya bingung tentang Drupal 8.

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

Jawaban:


69

Ada dua jenis blok, dan metode untuk merender keduanya agak berbeda:

Blok Konten

Blok konten adalah blok yang Anda buat di antarmuka. Mereka seperti struktur data yang dapat dikonfigurasi node, dengan bidang, dll. Jika Anda ingin merender salah satunya, Anda dapat melakukan apa yang biasanya Anda lakukan dengan entitas, memuatnya dan merendernya dengan pembuat tampilan:

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

Blok plugin

Blok juga bisa berupa plugin, didefinisikan dalam berbagai modul. Contohnya bisa menjadi blok remah roti. Jika Anda ingin merendernya, Anda harus menggunakan blok plugin manager.

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

Entitas konfigurasi

Dibagi untuk dua jenis adalah blok, adalah bahwa begitu Anda memasukkannya ke suatu wilayah, Anda akan membuat entitas konfigurasi yang memiliki semua pengaturan untuk blok. Dalam beberapa kasus akan lebih berguna menangani entitas konfigurasi. Karena blok yang sama dapat ditempatkan di beberapa wilayah dengan dan dengan konfigurasi yang berbeda, itu bisa menjadi lebih rumit menggunakan entitas konfigurasi blok. Yang menyenangkan adalah Anda mungkin ingin membuat blok dengan konfigurasi tertentu, yang buruk adalah bahwa konfigurasi bisa berubah dengan mengacaukan antarmuka, sehingga kode mungkin berakhir tidak berfungsi setelah membiarkan pengguna menggunakan antarmuka blok.

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

2
Pertanyaannya tidak menentukan apakah ini tentang render entitas konfigurasi blok (penempatan blok pra-konfigurasi) atau plugin blok dengan konfigurasi hardcoded. Yang masuk akal karena perbedaan itu tidak ada di 7.x. Ini lebih fleksibel karena yang lain sebenarnya membutuhkan blok khusus yang perlu ditempatkan dalam tema dan wilayah tertentu. Namun, Anda tidak boleh membuatnya dengan tangan. Gunakan metode createInstance () blok manager untuk itu dengan ID plugin, di mana Anda juga dapat memberikan array konfigurasi $ ...
Berdir

2
Selain itu, Anda mungkin ingin mempertimbangkan untuk memanggil metode akses () terlebih dahulu jika akses blok dibatasi untuk misalnya izin tertentu oleh blok itu. Bisakah Anda sedikit memperbaiki jawaban Anda tentang itu? Maka bisa menjadi sumber yang bermanfaat :)
Berdir

1
@Berdir Sudah lama, tapi saya akhirnya memperbaiki jawabannya. Dengan semua berbagai caching yang terjadi, menggunakan plugin secara langsung mungkin hanya berguna dalam situasi terbatas.
googletorp

4
Kelemahan dengan menggunakan block plugin manager createInstance () adalah bahwa array render yang dihasilkan tidak berjalan melalui blok theming, jadi Anda tidak dapat menggunakan blok - blockname.twig.html, misalnya. Alternatifnya adalah membuat blok untuk tema Anda, tetapi biarkan dinonaktifkan, dan kemudian dalam kode Anda, lakukan: `` `$ block = \ Drupal \ block \ Entity \ Block :: load ('myblock'); $ build = \ Drupal :: entityManager () -> getViewBuilder ('block') -> view ($ block); `` `
joachim

1
Tidak - Lubang kelinci lainnya. Kode untuk blok konten layar putih (dengan terkenal "Situs web mengalami kesalahan tak terduga. Silakan coba lagi nanti.") Yang kedua semakin dekat - Tetapi menampilkan pesan samar tentang blok yang hilang atau sesuatu ... (yang tidak itu benar karena saya sedang mencoba blok sistem - yang didukung oleh hal drupal).
sea26.2

16

Untuk menampilkan hanya blok Anda di template Anda dengan preprocess, cara terbaik adalah

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

Dan di Anda page.html.twigatau node.html.twigatau xxx.html.twiggunakan variabel My_region Anda seperti ini:

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

Dan dalam array yang dapat di render (modul khusus) dengan contoh menjadi kustom kontroler dalam konten ():

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,
      );
}

Menggunakan drupal_rendertidak berguna karena Drupal sudah menganggap render di D8 dan ini sudah usang . Anda harus menggunakannya \Drupal::service('renderer')->renderRoot()sebagai gantinya.

Agak berat, lebih baik menggunakan sistem area maksimum dan tidak menambahkan blok beban dari preproses. Dalam hal menggunakan pengontrol di modul Anda, ini sepertinya penggunaan yang dibenarkan.


Implementasi pengontrol ini adalah persis apa yang saya cari. Terima kasih!
Mrweiner

Saya tertarik dengan implementasi pengontrol ini untuk kasus penggunaan serupa yang saya hadapi. Tetapi saya tidak dapat menemukan dokumentasi tentang element-contentproperti dalam array render. Apakah Anda tahu di mana itu didokumentasikan?
Eria

Saya tidak tahu mengapa, tetapi \Drupal\block\Entity\Block::loadtidak mengembalikan blok sepanjang waktu. Ini hanya mengembalikan sesuatu jika blok I memuat ditempatkan dalam tampilan di tata letak blok . Jika tidak ditempatkan, ia mengembalikan null.
Arthur Attout

Jawaban ini harus diperbarui untuk digunakan\Drupal::entityTypeManager()->getViewBuilder('block')->view($block);
Ryan Hartman

6

Selain jawaban teratas ... Jika Anda ingin membuat blok dari tampilan, Anda mungkin harus melakukan hal-hal yang sedikit berbeda.

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

(nama tampilan misalnya -> blok_1)

Karena kita akan meneruskannya ke ranting, kita tidak perlu me-render (menggunakan layanan render).

Jadi Anda bisa meneruskannya sebagai variabel ke ranting (untuk contoh ini, ini adalah kembalinya Controller):

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

dalam modul Anda, Anda memerlukan hook_theme () untuk variabel Anda:

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

Dan akhirnya di template ranting Anda:

{{ your_variable }}

5

Saya perlu mendapatkan HTML blok khusus dan menggunakannya:

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

print $d->__toString();

1
Saya perlu menambahkannya ke render array dan di sana itu berfungsi tanpa __toString().
leymannx

1
Penting untuk menyebutkan bahwa setidaknya satu blok harus ditempatkan di wilayah "Blok yang dinonaktifkan". Atau wilayah aktif lainnya.
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));

Jika memungkinkan, Anda harus menghindari penggunaan drupal_renderatau layanan render. drupal_renderdihapus tetapi mempertahankan render array dengan konten yang diberikan cukup buruk, Anda harus kembali $block_content, render array dapat diubah sebelum render yang sebenarnya dan Anda harus membiarkan Drupal melakukan rendering sebanyak mungkin, atau melakukannya sendiri.
googletorp

Ini hanya akan berfungsi jika blok sudah ditempatkan pada halaman melalui tata letak blok.
hugronaphor

1

Pada dasarnya, ada dua jenis render.

  1. Ketika ada contoh yang ada dari blok dalam tata letak. blok dapat dirender dalam ranting menggunakan preprocess sebagai

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

  2. Tidak ada instance atau konfigurasi untuk blok. Kemudian di preprocessor, kita perlu membuat instance, membangun blok dan kemudian merendernya

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


0

Sepertinya ini berfungsi untuk blok plugin ..

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

-2

Anda mendapatkan blok keluaran:

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

Dan kemudian Anda dapat mengembalikan output dengan berbagai cara:

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

atau:

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

\Drupal::service ('renderer')->render ($block_content)dapat dilakukan karena drupal_render ($block_content)Namun yang terakhir ini ditinggalkan dalam Drupal 8.
olegiv

Jika memungkinkan, Anda harus menghindari penggunaan drupal_renderatau layanan render. drupal_renderdihapus tetapi mempertahankan render array dengan konten yang diberikan cukup buruk, Anda harus kembali $block_content, render array dapat diubah sebelum render yang sebenarnya dan Anda harus membiarkan Drupal melakukan rendering sebanyak mungkin, atau melakukannya sendiri. Apa yang Anda kembalikan harus dirender lagi, yang menjadikan rendering yang sebenarnya tidak berguna
googletorp

-2

Berdasarkan penelitian saya, Anda dapat mendasarkan kode dari Cara membuat blok secara program di drupal 8 . Anda juga bisa berubah

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

menjadi sesuatu yang sederhana seperti:

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

untuk melampirkannya misalnya ke variabel pengembalian halaman.


Jika memungkinkan, Anda harus menghindari penggunaan drupal_renderatau layanan render. drupal_renderdihapus tetapi mempertahankan render array dengan konten yang diberikan cukup buruk, Anda harus kembali $block_content, render array dapat diubah sebelum render yang sebenarnya dan Anda harus membiarkan Drupal melakukan rendering sebanyak mungkin, atau melakukannya sendiri.
googletorp

Kamu benar. Ini bukan solusi yang disarankan dan paling fleksibel.
Leolando Tan

Tautan Anda mati "Cara merender blok ..."
sea26.2
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.