1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

未だ意味不明の wire / drupal で遊んでいきます。
前回はチュートリアルをコピペしてカウンターを作成しました。

今回は記事一覧ページコンポーネントを生成してます。
実装内容はほぼ公式のトップページの内容となっています。

準備

コマンドでコンポーネントを作成

drush generate wire

対話の内容
スクリーンショット 2023-07-26 22.51.15.png
エンティティクエリを使用するため、entity_type.managerを選択しています。

生成されたファイル

ArticleList.php
class ArticleList extends WireComponent {

  protected ?EntityTypeManagerInterface $entityTypeManager;

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

  /**
   * {@inheritdoc}
   */
  public function render(): ?View {
    return View::fromTpl('article_list');
  }

}

記事一覧を取得し表示

render() メソッド内でノードを取得してみます。

  public function render(): ?View {
    $node_storage = $this->entityTypeManager->getStorage('node');
    $nids = $node_storage->getQuery()
      ->accessCheck(TRUE)
      ->condition('type', 'article')
      ->condition('status', 1)
      ->execute();
    if (empty($nids)) {
      return NULL;
    }
    $nodes = $node_storage->loadMultiple($nids);

    // 第2に引数にテンプレートに渡す値を設定.
    return View::fromTpl('article_list', [
      'nodes' => $nodes,
    ]);
  }

エンティティクエリを使用して事前に作っておいた aritcle コンテンツタイプからすべての記事を取得しました。
エンティティクエリはこちらの記事を参照しました。

テンプレートで表示してみます。

article_list.html.twig
<div>
  <ul>
    {% for node in nodes %}
      <a href="{{ path('entity.node.canonical', {'node': node.id}) }}">
        <li>{{ node.label }}</li>
      </a>
      タグ: {{ node.field_tags.entity.label }}
    {% endfor %}
  </ul>
</div>

パスはこちらのドキュメントを参照しました。
タグはタクソノミーで実装しており、エンティティ参照フィールドなので node.{エンティティ参照フィールド}.entity.{取得したい値} といった形で参照します。

結果
スクリーンショット 2023-07-26 23.13.31.png

一旦表示はできました。
ただ表示するだけでは Drupal デフォルトの機能を使うほうが良さ気です。

リアクティブコンポーネントの作成に JS フレームワークは必要ありません

とあるので、リアクティブに動作するか確認するため検索機能を追加してみます。

検索機能

フロントから値をPHPに渡す必要があるのでそれようの input タグを用意します。

article_list.html.tiwg
  <input
    wire:model="search"
    type="search"
    placeholder="Search by title..."
  >

次にバックエンドです。
まずプロパティとして wire:model でセットした search を定義します。

  /**
   * 検索ワード.
   *
   * @var string
   */
  public string $search = '';

さらにフロントから受け取った値 $search で絞り込みができるようクエリを書き換えます。

    $nids = $node_storage->getQuery()
      ->accessCheck(TRUE)
      ->condition('type', 'article')
      ->condition('status', 1)
      // 追加分
      ->condition('title', '%' . addcslashes($this->search, '\%_') . '%', 'LIKE')
      ->execute();

結果
pで検索するとリロードなく特定の記事だけに絞り込めました。
スクリーンショット 2023-07-29 10.25.45.png

ただこの実装だと問題がありました。
NULL を返すとだめっぽいです。

    if (empty($nids)) {
      return NULL;
    }

以下のように変更してみました。

    if (empty($nids)) {
      return View::fromTpl('article_list', [
        'message' => '記事が見つかりませんでした。',
      ]);
    }

さらに twig も変更し nodes がないときは message を表示するようにしました。

  <ul>
    {% if nodes %}
      {% for node in nodes %}
        <a href="{{ path('entity.node.canonical', {'node': node.id}) }}">
          <li>{{ node.label }}</li>
        </a>
        タグ: {{ node.field_tags.entity.label }}
      {% endfor %}
    {% else %}
      {{ message }}
    {% endif %}
  </ul>

無事動作しました。

スクリーンショット 2023-07-29 23.02.38.png

まとめ

  • JS を書かずに PHP と Twig だけで最近のJSライブラリのような実装ができる。
  • REST API とかヘッドレスとかに食って掛かりそうでちょっと楽しみ。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?