Bir bloğu programlı olarak nasıl görüntüleyebilirim?


33

Drupal 8 beta-14 kullanarak bir site geliştiriyorum. Farklı terimlerden oluşan bir görünüm bloğu oluşturdum ve şimdi kodu kullanarak görüntülemek istiyorum. Programlı olarak nasıl görüntüleyebilirim? Bu kodu kullanarak Drupal 7'de yapardım ama Drupal 8 ile ilgili kafam karıştı.

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

Yanıtlar:


69

İki tür blok vardır ve ikisini oluşturma yöntemi biraz farklıdır:

İçerik Blokları

İçerik blokları, arayüzde oluşturduğunuz bloklardır. Bunlar, yapılandırılmış veri yapılarına, alanlar vb. Gibi düğümlere benzer. Bunlardan birini oluşturmak istiyorsanız, normal olarak varlıklar ile yapacağınız şeyi yapabilir, yükleyebilir ve görünüm oluşturucu ile oluşturabilirsiniz:

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

Eklenti blokları

Bloklar ayrıca çeşitli modüllerde tanımlanmış eklenti olabilir. Bir örnek, breadcrumb bloğu olabilir. Bunları oluşturmak istiyorsanız, blok eklenti yöneticisini kullanmanız gerekir.

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

Varlıkları yapılandır

İki tür için paylaşılan bloklardır; bir bölgeye eklediğinizde, blok için tüm ayarlara sahip bir yapılandırma öğesi oluşturacaksınız. Bazı durumlarda konfigürasyon işlemlerini yapmak daha yararlı olacaktır. Aynı blok farklı konfigürasyonlu ve farklı çoklu bölgelere yerleştirilebildiğinden, blok konfigürasyon varlıkları kullanılarak daha zor olabilir. İşin güzel yanı, belirli bir yapılandırmaya sahip bir blok oluşturmak isteyebilirsiniz, kötü olan şey, yapılandırma kimliklerini arayüzle uğraştırarak değiştirebilmeleridir, bu nedenle kullanıcıların blok arayüzünü kullanmasına izin verdikten sonra kod çalışmayabilir.

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

2
Soru, bir blok yapılandırma öğesi (önceden yapılandırılmış bir blok yerleşimi) mi yoksa sabit kodlanmış yapılandırmaya sahip bir blok eklentisi mi oluşturduğunu belirtmiyor. Bu mantıklı çünkü bu fark 7.x'te yok. Bu daha esnektir, çünkü diğeri aslında belirli bir temaya ve bölgeye yerleştirilmesi gereken belirli bir blok gerektirir. Ancak, onları asla elle yaratmamalısınız. Bir eklenti ID'si için blok eklentisi yöneticisinin createInstance () metodunu kullanın, burada $ configuration dizisi de sağlayabilirsiniz ...
Berdir

2
Ayrıca, blok erişiminin, örneğin bu blok tarafından belirli bir izinle sınırlandırılması durumunda, öncelikle access () yöntemini çağırmayı düşünebilirsiniz. Bu konudaki cevabını biraz geliştirebilir misin? Sonra yararlı bir kaynak olabilir :)
Berdir

1
@Berdir Uzun zaman oldu ama nihayetinde cevabı iyileştirmek için uğraştım. Tüm çeşitli önbellekleme işlemleri devam ederken, eklentiyi doğrudan kullanmak, yalnızca sınırlı durumlarda yararlı olabilir.
googletorp

4
Blok eklentisi yöneticisini kullanmanın olumsuz tarafı, createInstance (), elde edilen render dizisinin blok temaları boyunca çalıştırılmamasıdır, bu nedenle bloğu kullanamazsınız, örneğin blockname.twig.html. Alternatif, temanız için bir blok oluşturmaktır, ancak onu devre dışı bırakın ve ardından kodunuzda yapın: `` `$ block = \ Drupal \ block \ Entity \ Block :: load ('myblock'); $ build = \ Drupal :: entityManager () -> getViewBuilder ('blok') -> görünüm ($ blok); `` `
joachim

1
Hayır - Başka bir tavşan deliği. İçerik bloğu beyaz ekranlarının kodu (rezil "Web sitesi beklenmedik bir hatayla karşılaştı. Lütfen daha sonra tekrar deneyin.") İkincisi daha da yaklaşıyor - Ancak bloğun eksik olduğu veya hakkında bir şeyler hakkında şifreli bir mesaj görüntüleniyor ... doğru değil çünkü ben bir sistem bloğunu deniyorum - bu güçlü bir şey tarafından destekleniyor).
deniz26.2

16

Önceden işlenmiş şablonlarınızda sadece blokunuzu görüntülemek için en iyi yol

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

Ve sizin page.html.twigya node.html.twigda xxx.html.twigdeğişken My_region değişkeninizi şöyle kullanın:

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

Ve renderable dizisinde (custom module) örnek olarak content () 'deki custom denetleyicisine:

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

kullanma drupal_renderDrupal'ın zaten D8'deki görüntüleyiciyi varsaydığı ve bu kullanımdan kaldırıldığı için kullanışlı değildir . Bunun \Drupal::service('renderer')->renderRoot()yerine kullanmalısın .

Biraz ağırdır, maksimum alan sistemini kullanmak daha iyidir ve ön işlemden yükleme bloğu eklemez. Modüllerinizde bir kontrol cihazı kullanılması durumunda bu haklı bir kullanım gibi görünüyor.


Bu denetleyici uygulaması tam olarak aradığım şeydi. Teşekkürler!
Mrweiner

Bu kontrolörün uygulanması ile uğraştığım benzer bir kullanım durumuyla ilgileniyorum. Ancak element-contentbir render dizisindeki özelliklerle ilgili herhangi bir belge bulamıyorum . Nerede belgelendiğini biliyor musun?
Eria

Nedenini bilmiyorum, ama \Drupal\block\Entity\Block::loadher zaman bir blok döndürmüyor. Bu sadece bir şey döndürürüm, yüklediğim blok görünümün içine blok düzeninde yerleştirilmişse döndürür . Yerleştirilmezse null değerini döndürür.
Arthur Attout

Bu cevap kullanmak için güncellenmelidir\Drupal::entityTypeManager()->getViewBuilder('block')->view($block);
Ryan Hartman

6

En iyi cevaba ek olarak ... Bir görünümden bir blok oluşturmak istiyorsanız, işleri biraz daha farklı yapmanız gerekebilir.

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

(görünen ad, örneğin -> blok_1)

Bunu dallara geçireceğimizden, renderlemeye ihtiyacımız yok (render servisini kullanarak).

Yani onu sadece dal için bir değişken olarak geçirebilirsiniz (bu örnekte, bir Denetleyicinin dönüşü):

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

modülünüzde değişkeniniz için bir hook_theme () gerekir:

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

Ve sonunda dal şablonunuzda:

{{ your_variable }}

5

Özel bir bloğun HTML kodunu almam ve onu kullanmam gerekiyordu:

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

print $d->__toString();

1
Bir render dizisine eklemem gerekiyordu ve orada olmadan çalıştı __toString().
leymannx

1
En azından "Engelli bloklar" bölgesinde bir bloğun yerleştirilmesi gerektiğini belirtmek önemlidir. Veya diğer aktif bölgeler.
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));

Mümkünse, kullanmaktan drupal_renderveya render hizmetinden kaçınmalısınız . drupal_rendergösterilmiyor ancak bir renderin renderlenmiş içeriğe sahip bir diziyi geri $block_contentçekmesi oldukça kötü, bunun yerine geri dönmelisiniz, render dizisi gerçek renderden önce değiştirilebilir ve Drupal'ın renderu istediğiniz kadar yapmasına veya kendin yapmasına izin vermelisiniz.
googletorp

Bu sadece, blok zaten sayfada blok düzeni ile yerleştirilmişse işe yarayacaktır.
hugronaphor

1

Temel olarak, iki tür render vardır.

  1. Düzende bloğun varolan bir örneği olduğunda. blok, önişlemsel olarak kullanılarak dal içinde oluşturulabilir.

    $ block = Blok :: yük ('BLOCK_ID'); $ değişkenleri ['social_links'] = \ Drupal :: entityTypeManager () -> getViewBuilder ('blok') -> görünüm ($ blok);

  2. Blok için örnek veya yapılandırma yok. Sonra önişlemcide, örneği oluşturmamız, bloğu yapmamız ve sonra oluşturmamız gerekiyor.

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


0

Bu eklenti blokları için çalışıyor gibi görünüyor ..

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

-2

Blok çıktısı alıyorsunuz:

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

Ve sonra çıktıyı farklı şekillerde iade edebilirsiniz:

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

veya:

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

\Drupal::service ('renderer')->render ($block_content)olarak yapılabilir drupal_render ($block_content)Ancak ikincisi 8. Drupal önerilmiyor
olegiv

Mümkünse, kullanmaktan drupal_renderveya render hizmetinden kaçınmalısınız . drupal_rendergösterilmiyor ancak bir renderin renderlenmiş içeriğe sahip bir diziyi geri $block_contentçekmesi oldukça kötü, bunun yerine geri dönmelisiniz, render dizisi gerçek renderden önce değiştirilebilir ve Drupal'ın renderu istediğiniz kadar yapmasına veya kendin yapmasına izin vermelisiniz.
İade ettiğiniz şeylerin

-2

Araştırmamı temel alarak , drupal 8'deki programlı bir bloğu nasıl programlayacağınız kodunu temel alabilirsiniz . Ayrıca değişebilir

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

kadar basit bir şeye:

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

örneğin bir sayfanın dönüş değişkenine eklemek için.


Mümkünse, kullanmaktan drupal_renderveya render hizmetinden kaçınmalısınız . drupal_rendergösterilmiyor ancak bir renderin renderlenmiş içeriğe sahip bir diziyi geri $block_contentçekmesi oldukça kötü, bunun yerine geri dönmelisiniz, render dizisi gerçek renderden önce değiştirilebilir ve Drupal'ın renderu istediğiniz kadar yapmasına veya kendin yapmasına izin vermelisiniz.
googletorp

Haklısın. Bu önerilen ve en esnek çözüm değil.
Leolando Tan,

Bağlantınız bitti "Nasıl blok yapılır ..."
deniz26.2
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.