異なるリージョンでノードのフィールドを表示するためのベストプラクティスは何ですか?


7

D7では、ノードのビューを作成するために使用しました。各フィールドには独自の表示があります。各ディスプレイは、サイトの任意の領域に配置するブロックを作成します。しかしもちろん、ビューはSQLを多用します。

今、Drupal 8はすべてファンシーです。ページの異なる領域にあるノードのフィールドを表示するDrupal 8の方法は何ですか?

編集:私の現在の試みは、指定された各フィールドにブロックを提供するカスタムモジュールを作成することです。

回答:


4

なぜすべてのフィールドを個別のブロックにしたいのか正確にわかりませんか?他に何もないとしても、それはかなり非効率的です。

1つまたは2つのブロックを追加するには、ctoolsモジュールによって提供されるエンティティビューブロックを使用できます。現在のノードを取得し、特定のビューモードで表示します。もちろん、すべてのフィールドが別々になっていると、それを維持するのは大変ですが、なぜそうしたいのか本当にわかりませんか?


たとえば、ノードには「サイドバー」というフィールドがあります。もちろん、そのフィールドのコンテンツは、通常の「コンテンツ」の外側の別のリージョンにレンダリングする必要があります。
Alex

3

D8のCtoolsには、ページマネージャーのさまざまなレイアウトでこれを実行できるChaos toolsブロックと呼ばれる実験的なモジュールが付属しています。

これは、コンテンツタイプを表示するノードバリアントを作成する場合に非常に役立ちます。

有効にした後、表示されているノードから任意のフィールドを追加できます。ブロックの追加をクリックすると、「コンテンツ」の下で利用可能なフィールドの完全なリストが表示されます。

欠点は、モジュールが実験的なものであり、利用できるドキュメントがあまりないことです。

ここにそれについてのアクティブなスレッドがありますhttps://www.drupal.org/node/2809213

モジュールページhttps://www.drupal.org/project/ctools

私はそれを自分で試してみましたが、うまくいきます。

これがあなたやこの種のシナリオの解決策を探している人を助けることを願っています。


2

Drupal 8のさまざまなリージョンでノードのフィールドを表示するためのベストプラクティスは何ですか?

そのためのベストプラクティスはない、おそらく良いプラクティスではないかもしれませんが、いくつかのオプションに従ってください。

私にとってはこれが最良のオプションです。現在のノードをロードして目的のnode_fieldを表示するブロックを作成できます。このようにして、UIを介して簡単に管理できます( 'node_type' selectおよび 'field_name' selectを使用したブロックは、簡単かつ迅速に実行できます)。


編集の開始1
ここで、そのブロックの実装をテストし、結果をコメントしてください

<?php
/**
 * @file
 * Contains \Drupal\ module_name\Plugin\Block\NodeFieldBlock.
 */

namespace Drupal\module_name\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\field\Entity\FieldConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Provides a Filter by vocabulary terms block.
 *
 * @Block(
 *   id = "node_field_block",
 *   admin_label = @Translation("Node Field")
 * )
 */
class NodeFieldBlock extends BlockBase implements ContainerFactoryPluginInterface {
  /**
   * The Entity Type Manager.
   *
   * @var Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The Entity Field Manager.
   *
   * @var Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The Entity Display Repository.
   *
   * @var Drupal\Core\Entity\EntityDisplayRepository
   */
  protected $entityDisplayRepository;

  /**
   * Dependency injection through the constructor.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin ID for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_type_manager
   *   The Entity Type Manager.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   The Entity Field Manager.
   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
   *   The Entity Display Repository.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition,
  EntityTypeManagerInterface $entity_type_manager,
  EntityFieldManagerInterface $entity_field_manager,
  EntityDisplayRepositoryInterface $entity_display_repository) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFieldManager = $entity_field_manager;
    $this->entityDisplayRepository = $entity_display_repository;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('entity_field.manager'),
      $container->get('entity_display.repository')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return array(
      'node_type' => array_keys(node_type_get_names())[0],
      'view_mode' => 'default',
      'field' => '',
    );
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {
    $types = node_type_get_names();
    $config = $this->configuration;
    if ($node_type = $form_state->getValue(array('settings', 'node_type'))) {
      $config['node_type'] = $node_type;
    }

    $form['node_type'] = array(
      '#title' => $this->t('Content type'),
      '#type' => 'select',
      '#options' => $types,
      '#default_value' => $config['node_type'],
      '#ajax' => array(
        'callback' => array(get_class($this), 'updateFieldList'),
        'wrapper' => 'edit-node-wrapper',
      ),
    );

    $form['options'] = array(
      '#type' => 'container',
      '#prefix' => '<div id="edit-node-wrapper">',
      '#suffix' => '</div>',
    );

    $form['options']['view_mode'] = array(
      '#title' => $this->t('View mode'),
      '#type' => 'select',
      '#multiple' => FALSE,
      '#options' => $this->getViewModes($config['node_type']),
      '#default_value' => $config['view_mode'],
    );

    $form['options']['field_list'] = array(
      '#title' => $this->t('Field list'),
      '#type' => 'select',
      '#multiple' => FALSE,
      '#options' =>  $this->getFieldList($config['node_type']),
      '#default_value' => $config['field'],
    );

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['node_type'] = $form_state->getValue('node_type');
    $this->configuration['view_mode'] = $form_state->getValue(array('options', 'view_mode'));
    $this->configuration['field'] = $form_state->getValue(array('options', 'field_list'));
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $config = $this->configuration;
    $build = array();
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      if ($config['node_type'] == $node->getType()) {
        if ($field = $node->get($config['field'])) {
          $build['field'] = $field->view($config['view_mode']);
        }
      }
    }
    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      return Cache::mergeTags(parent::getCacheTags(), array('node:' . $node->id()));
    } else {
      return parent::getCacheTags();
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return Cache::mergeContexts(parent::getCacheContexts(), array('route'));
  }

  /**
  * Função que cria uma lista de fields de um node type.
  *
  * @param string $node_type
  *   O id do node type.
  * @return array
  *   Retorna a lista de campos do node type.
  */
  protected function getFieldList($node_type) {
    if (!empty($node_type)) {
      $list = $this->entityFieldManager->getFieldDefinitions('node', $node_type);
      foreach ($list as $id => $field) {
        if ($field instanceof FieldConfig) {
          $list[$id] = $field->label();
        } else {
          unset($list[$id]);
        }
      }
      return $list;
    }
    return array();
  }

  /**
  * Função que cria uma lista de view modes de um node type.
  *
  * @param string $node_type
  *   O id do node type.
  * @return array
  *   Retorna a lista de view mode do node type.
  */
  protected function getViewModes($node_type) {
    return $this->entityDisplayRepository->getViewModeOptionsByBundle('node', $node_type);
  }

  /**
   * Handles switching the node type selector.
   */
  public static function updateFieldList(&$form, FormStateInterface &$form_state, Request $request) {
    return $form['settings']['options'];
  }
}

編集を終了1


または...フィールドを取得して変数にpreprocess_regionロードします(これは簡単に説明できます)。

function THEME_preprocess_region(&$variables) {
  //TODO: change for you region name
  if ($variables['region'] == 'sidebar_right') {
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      //TODO: change for you node type
      if ($node->getType() == 'article') {
        //If you need a flag for this type
        $variables['is_article'] = TRUE;
        //Here is your field
        $variables['node_field'] = $node->get('field_descricao')->view();
      }
    }
  }
}

そして、あなたの小枝ファイルで使用してください

{% if node_field %} 
  {{ node_field }}
{% endif %}

注意:
今後、このフィールドを削除することはできません。削除すると、ページが破損します。説明:$node->get('field_descricao')nullを評価しない場合、null->view()=ページを壊します。あなたがこれを世話しても、誰かまたはあなたはこれを忘れることができ、なぜその情報がもう表示されないのか頭痛になります。


それは病気の答えです!後で試してみる
アレックス

パフォーマンスとキャッシングはどうですか?このパフォーマンスですか?
Alex

1
それは問題ありません。ビルドフェーズでは、1つの要素(ルックアップなし、ビルドリストなし...存在するかどうかを確認するだけ)だけをレンダリングします。このブロックが構築されるすべてのルート(getCacheContexts)、特定のタイプのノードがある場合、フィールドをレンダリングします。そして、はい、2回目にアクセスした場合、キャッシュが使用されます。ノードを変更すると、ブロックは再構築されます(getCacheTags)。この場合(ブロックはノード情報を取得)、ブロックオブジェクトはキャッシュ情報をオーバーライドする必要があります。そうでない場合、ブロックは1回だけ構築され、あらゆる場所で使用されます。
Vagner 2016年

1

たとえば、ノードには「サイドバー」というフィールドがあります。もちろん、そのフィールドのコンテンツは、通常の「コンテンツ」の外側の別のリージョンにレンダリングする必要があります。-アレックス18時間前

テーマのレイアウトとサイドバー領域を使用する代わりに、次のモジュールのいずれかを使用して、サイドバー領域を持つパネルまたはディスプレイスイートレイアウトを作成できます。次に、ノードフィールドと必要な他のブロックをサイドバーや作成した他のリージョンに挿入できます。

パネル

パネルモジュールを使用すると、サイト管理者は複数の用途に合わせてカスタマイズされたレイアウトを作成できます。その中心となるのは、レイアウトを視覚的に設計してそのレイアウト内にコンテンツを配置できるドラッグアンドドロップコンテンツマネージャーです。他のシステムとの統合により、これを使用するノード、これを使用するランディングページを作成し、分類法やノードページなどのシステムページをオーバーライドして、非常に細かい権限でサイトのレイアウトをカスタマイズできます。

ディスプレイスイート

Display Suiteでは、ドラッグアンドドロップインターフェイスを使用してコンテンツの表示方法を完全に制御できます。ノード、ビュー、コメント、ユーザーデータなどを、何十ものテンプレートファイルを操作しなくても、好きなように配置できます。


私はこれらのモジュールを知っています。彼らは高性能ですか?たとえば、ビューはノードが既にロードされているにもかかわらず追加のSQLクエリを実行するため、かなりSQLが重い
Alex

1
歴史的に、これらのモジュールは経年とともに改善されてきました。D8バージョンのパフォーマンス測定はまだ見ていませんが、どちらもパフォーマンスを重視する企業によって構築および使用されています。したがって、今日のように十分に構築されていなければ、すぐに構築されると思います。
アクロマン

1

フィールドブロックモジュールは、あなたが求めているものをほとんどありません。これにより、任意のエンティティタイプ/バンドルの任意のフィールドを、お好みの領域のブロックとして表示できます。


残念ながら、すべてのコンテンツタイプとフィールドのブロックが作成され、多くのブロックが発生します:/
Alex

0

クイック編集機能を使用する場合は、UIを介してさまざまなビューモードを作成して使用できます(構造/表示モード/ビューモードの下)。つまり、ティーザーモードとフルビューモードだけに限定されるわけではありません。また、ビューでカスタムビューモードを使用することもできます。そして、そのような方法でレンダリングされたコンテンツには、必要なすべてのコンテキストリンクがあります。


しかし、それはすべてのフィールドに表示モードを作成する必要があることを意味しますか?
アレックス

いいえ、ノードの新しい表示モードを作成し、コンテンツタイプの[表示の管理]タブで調整できます。各ビューモード(フィールドディスプレイのセットと見なされます)は、他のモードとは別に調整できます。
Stanislav Agapov

-1

Drupal 7では、以前はAlexとまったく同じことを行っていました。コンテンツをブロックに配置するビューを作成しました。私はこのスレッドがQuickEditを動作させる方法を探しているのを見つけました。
Display SuiteとViewModesが答えのようです。

これは私にとって最もクリーンな方法のようです。Drupal8バージョンのDisplay Suiteを使用して、ノードからブロックにフィールドを追加できます。
詳しい説明はhttps://www.drupal.org/node/2754967にあります。このメソッドは、ビューの束を作成する手間を省き、インライン編集を可能にします。

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