मैं प्रोग्राम को ब्लॉक कैसे प्रदर्शित कर सकता हूं?


33

मैं Drupal 8 Beta-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;

संस्थाओं को कॉन्फ़िगर करें

दो प्रकारों के लिए साझा किए गए ब्लॉक हैं, यह है कि एक बार जब आप उन्हें एक क्षेत्र में सम्मिलित करते हैं, तो आप एक कॉन्फ़िगरेशन इकाई बनाएंगे जिसमें ब्लॉक के लिए सभी सेटिंग्स होती हैं। कुछ मामलों में यह विन्यास संस्थाओं से अधिक उपयोगी होगा। चूंकि एक ही ब्लॉक को विभिन्न क्षेत्रों में और अलग-अलग कॉन्फ़िगरेशन के साथ रखा जा सकता है, इसलिए यह ब्लॉक कॉन्फ़िगरेशन संस्थाओं का उपयोग करके अधिक पेचीदा हो सकता है। अच्छी बात यह है कि आप विशिष्ट कॉन्फ़िगरेशन वाले ब्लॉक को रेंडर करना चाहते हैं, बुरी बात यह है कि इंटरफ़ेस के साथ गड़बड़ करके कॉन्फिग आईडी बदल सकते हैं, इसलिए उपयोगकर्ताओं को ब्लॉक इंटरफ़ेस का उपयोग करने देने के बाद कोड काम नहीं कर सकता है।

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

2
यह निर्दिष्ट नहीं करता है कि यह ब्लॉक कॉन्फिग एंट्री (पूर्व-कॉन्फ़िगर ब्लॉक प्लेसमेंट) या हार्डकोड कॉन्फ़िगरेशन वाले ब्लॉक प्लगइन प्रदान करने के बारे में है। जो समझ में आता है क्योंकि वह अंतर 7.x में मौजूद नहीं है। यह अधिक लचीला है क्योंकि दूसरे को वास्तव में एक विशिष्ट ब्लॉक की आवश्यकता होती है जिसे किसी दिए गए विषय और क्षेत्र में रखा जाना चाहिए। हालाँकि, आपको उन्हें कभी हाथ से नहीं बनाना चाहिए। प्लगइन आईडी के साथ उस के लिए ब्लॉक प्लगइन मैनेजर के createInstance () विधि का उपयोग करें, जहां आप $ कॉन्फ़िगरेशन सरणी भी प्रदान कर सकते हैं ...
Berdir

2
इसके अलावा, आप कॉल को एक्सेस करने पर विचार कर सकते हैं () विधि पहले ब्लॉक ब्लॉक का उपयोग उस ब्लॉक द्वारा एक निश्चित अनुमति के लिए प्रतिबंधित है। क्या आप उस पर अपना उत्तर थोड़ा सुधार सकते हैं? तब एक उपयोगी संसाधन बन सकता है :)
बर्दिर

1
@Berdir थोड़ी देर हो गई है, लेकिन मैं आखिरकार जवाब को सुधारने के लिए इधर-उधर हो गया। सभी विभिन्न कैशिंग के साथ, सीधे प्लगइन का उपयोग करना संभवतः सीमित स्थितियों में ही उपयोगी है।
googletorp

4
ब्लॉक प्लगइन मैनेजर createInstance () का उपयोग करने के साथ नकारात्मक पक्ष यह है कि परिणामस्वरूप रेंडर सरणी ब्लॉक थीमिंग के माध्यम से नहीं चलती है, इसलिए आप उदाहरण के लिए ब्लॉक - blockname.twig.html का उपयोग नहीं कर सकते हैं। विकल्प यह है कि आप अपनी थीम के लिए एक ब्लॉक बनाएं, लेकिन इसे अक्षम छोड़ दें, और फिर अपने कोड में करें: `` $ ब्लॉक = \ Drupal \ block \ Entity \ Block :: load ('myblock'); $ बिल्ड = \ Drupal :: unitManager () -> getViewBuilder ('ब्लॉक') -> दृश्य ($ ब्लॉक); `` `
जोशिम

1
नोप - एक और खरगोश छेद। कंटेंट ब्लॉक व्हाइट स्क्रीन के लिए कोड (बदनाम के साथ "वेबसाइट को एक अप्रत्याशित त्रुटि का सामना करना पड़ा। कृपया बाद में पुन: प्रयास करें।)) दूसरा करीब हो जाता है - लेकिन ब्लॉक के गुम होने या कुछ और होने के बारे में एक गूढ़ संदेश प्रदर्शित करता है ... (जो isn है) 'सच है क्योंकि मैं एक सिस्टम ब्लॉक का प्रयास कर रहा हूं - ड्रुपल चीज द्वारा संचालित)।
समुद्र २६.२

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 %}

और सामग्री में एक नियंत्रक कस्टम में उदाहरण के द्वारा रेंडर करने योग्य सरणी (कस्टम मॉड्यूल) में:

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_renderड्रुपल उपयोगी नहीं है क्योंकि डी 8 में पहले से ही रेंडर को मान लिया गया है और इसे हटा दिया गया है । आपको \Drupal::service('renderer')->renderRoot()इसके बजाय उपयोग करना चाहिए ।

यह थोड़ा भारी है, अधिकतम क्षेत्र प्रणाली का उपयोग करना बेहतर है और प्रीप्रोसेस से लोड ब्लॉक नहीं जोड़ता है। अपने मॉड्यूल में नियंत्रक का उपयोग करने के मामले में यह एक उचित उपयोग लगता है।


यह नियंत्रक कार्यान्वयन वही है जो मैं देख रहा था। धन्यवाद!
मिस्टर

मैं इस नियंत्रक कार्यान्वयन में रुचि रखता हूं कि मैं इसी तरह के उपयोग के मामले के साथ काम कर रहा हूं। लेकिन मैं element-contentएक रेंडर सरणी में संपत्ति के बारे में कोई दस्तावेज नहीं ढूँढ सकता । क्या आप जानते हैं कि यह कहाँ प्रलेखित है?
एरिया

मुझे पता नहीं क्यों, लेकिन \Drupal\block\Entity\Block::loadहर समय एक ब्लॉक वापस नहीं करता है। यह केवल कुछ रिटर्न देता है यदि ब्लॉक I लोड को ब्लॉक लेआउट में दृश्य के भीतर रखा गया है । यदि इसे नहीं रखा गया है, तो यह अशक्त हो जाता है।
आर्थर एटआउट

इस उत्तर का उपयोग करने के लिए अद्यतन किया जाना चाहिए\Drupal::entityTypeManager()->getViewBuilder('block')->view($block);
रयान हार्टमैन

6

शीर्ष उत्तर के अलावा ... यदि आप किसी दृश्य से ब्लॉक को प्रस्तुत करना चाहते हैं, तो आपको कुछ अलग तरीके से काम करना पड़ सकता है।

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

(प्रदर्शन नाम जैसे -> ब्लॉक_1)

चूँकि हम इसे ट्विगी में पास करने जा रहे हैं, हमें रेंडर (सेवा प्रदान करने का उपयोग करके) करने की आवश्यकता नहीं है।

तो आप इसे केवल एक चर के रूप में पारित कर सकते हैं (उदाहरण के लिए, इसके नियंत्रक की वापसी):

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

आपके मॉड्यूल में आपको अपने वेरिएबल के लिए एक हुक_टैम () चाहिए:

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
यह उल्लेख करने के लिए महत्वपूर्ण है कि "अक्षम ब्लॉकों" क्षेत्र में कम से कम एक ब्लॉक रखा जाना चाहिए। या कोई अन्य सक्रिय क्षेत्र।
लीमैनएक्स

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इसके बजाय वापस लौटना चाहिए, रेंडर एरे को वास्तविक रेंडर से पहले बदल दिया जा सकता है और आपको ड्रुपल को रेंडर जितना पॉसिबल करना चाहिए या उसे स्वयं करने देना चाहिए।
googletorp

यह केवल तभी काम करने वाला है जब ब्लॉक को पहले ही ब्लॉक लेआउट के माध्यम से पृष्ठ पर रखा गया हो।
hugronaphor

1

मूल रूप से, दो प्रकार के रेंडर हैं।

  1. जब लेआउट में ब्लॉक का एक मौजूदा उदाहरण है। ब्लॉक को प्रीप्रोसेस के रूप में ट्विग में प्रस्तुत किया जा सकता है

    $ ब्लॉक = ब्लॉक :: लोड ('ब्लॉक_आईडी'); $ चर ['social_links'] = \ Drupal :: unitTypeManager () -> getViewBuilder ('ब्लॉक') -> दृश्य ($ ब्लॉक);

  2. ब्लॉक के लिए कोई उदाहरण या कॉन्फ़िगरेशन नहीं है। फिर प्रीप्रोसेसर में, हमें उदाहरण बनाने, ब्लॉक बनाने और फिर उसे रेंडर करने की आवश्यकता है

    $ block_manager = \ Drupal :: सेवा ('plugin.manager.block'); $ विन्यास = []; $ plugin_block = $ block_manager-> createInstance ('farmjournal_social_sharing', $ config); $ रेंडर = $ plugin_block-> build (); $ चर ['farmjournal_social_sharing'] = प्रस्तुत करना ($ प्रस्तुत करना);


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)हालांकि बाद में किया जा सकता है क्योंकि बाद में Drupal 8 में पदावनत कर दिया गया है
ऑलिविव

यदि संभव हो, तो आपको drupal_renderसेवा का उपयोग करने या प्रस्तुत करने से बचना चाहिए । drupal_renderप्रस्तुत किया गया है, लेकिन रेंडर की गई सामग्री के साथ एक एरे को रेंडर करना बहुत बुरा है, आपको $block_contentइसके बजाय वापस लौटना चाहिए, रेंडर एरे को वास्तविक रेंडर से पहले बदल दिया जा सकता है और आपको ड्रुपल को रेंडर जितना पॉसिबल करना चाहिए या उसे स्वयं करने देना चाहिए। क्या आप की जरूरत तरीके से प्रदान करने देता है, जो वास्तविक प्रतिपादन व्यर्थ बनाता है
googletorp

-2

मेरे शोध के आधार पर, आप ड्रुपल 8 में प्रोग्राम को ब्लॉक करने के तरीके से कोड को आधार बना सकते हैं । आप भी बदल सकते हैं

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

के रूप में सरल रूप में कुछ में:

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

उदाहरण के लिए इसे पृष्ठ के रिटर्न वैरिएबल में संलग्न करना।


यदि संभव हो, तो आपको drupal_renderसेवा का उपयोग करने या प्रस्तुत करने से बचना चाहिए । drupal_renderप्रस्तुत किया गया है, लेकिन रेंडर की गई सामग्री के साथ एक एरे को रेंडर करना बहुत बुरा है, आपको $block_contentइसके बजाय वापस लौटना चाहिए, रेंडर एरे को वास्तविक रेंडर से पहले बदल दिया जा सकता है और आपको ड्रुपल को रेंडर जितना पॉसिबल करना चाहिए या उसे स्वयं करने देना चाहिए।
googletorp

आप सही हे। यह अनुशंसित और सबसे लचीला समाधान नहीं है।
लेओलांडो टैन

आपका लिंक मर चुका है "कैसे एक ब्लॉक रेंडर करने के लिए ..."
Sea26.2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.