Skip to content

【システム】機能要望:ウィジェットに PHP Attribute ベースのクラス定義方式を追加してほしい #4331

@teratai3

Description

@teratai3

概要

現在のウィジェットは CakePHP 2〜3 系までの「らしさ」を残した実装と認識しています。
一方、CakePHP 自身は loadModel() の非推奨化や DI コンテナの導入など、より厳格でモダンな書き方へと進化しています。
baserCMS のコア部分もその流れに沿ってサービス層やインターフェース駆動の設計を取り入れており、
ウィジェットだけが取り残された状態になっているように感じています。

現状の認識

現在のウィジェット機能は templates/element/widget/ 以下に .php ファイルを配置する方式と理解しています。

plugins/bc-front/templates/element/widget/
├── text.php
├── search.php
├── local_navi.php
└── php_template.php

この方式はシンプルで導入しやすい反面、以下のような課題を感じています。

  • メタ情報を持てない:タイトルや説明などはファイル名・ディレクトリ走査から推測するしかない
  • ロジックとビューが分離しにくい:ウィジェット固有の処理をテンプレートに直書きする形になる
  • テストが書きにくい:クラスではないためユニットテストが困難
  • 実装の不明瞭さ:何を実装すべきかが不明確で、IDEの補完・静的解析が効かない

提案

PHP 8 のネイティブ Attribute を活用し、Drupal のプラグインシステムに近い形で、ウィジェットをクラスとして定義できるオプションを追加できないでしょうか。

baserCMS はすでに PHP 8.1 以上を要件としているため、Attribute は追加依存なしで利用できます。

イメージ

Attribute 定義

#[\Attribute(\Attribute::TARGET_CLASS)]
class Widget
{
    public function __construct(
        public readonly string $id,
        public readonly string $title,
        public readonly string $description = '',
        public readonly string $plugin = '',
        public readonly string $configElement = '',
    ) {}
}

ウィジェットクラスの例

#[Widget(
    id: 'text',
    title: 'テキスト',
    description: 'テキストコンテンツを表示します',
    plugin: 'BcWidgetText',
    configElement: 'Admin/widget/text_config',
)]
class TextWidget extends AbstractWidget
{
    public function render(array $settings): string
    {
        return $this->element('widget/text', $settings);
    }
}

AbstractWidget(基底クラス案)

abstract class AbstractWidget
{
    abstract public function render(array $settings): string;

    public function getDefaultSettings(): array
    {
        return [];
    }
}

起動時に全プラグインの src/Widget/ ディレクトリを走査し、#[Widget] Attribute を持つクラスを自動登録する WidgetRegistry のような仕組みがあると良いと考えています。

期待するメリット

現状(テンプレート方式) 提案(Attribute方式)
ディレクトリ走査でファイルを探す Attribute で自動登録
メタ情報なし(ファイル名のみ) クラスにメタ情報が付与される
ロジック記述が困難 クラスなのでロジックも自然に書ける
テスト不可 ユニットテストが書ける
IDEサポートなし 型安全・補完が効く

後方互換について

既存方式の廃止は破壊的な変更となるため、すぐに対応する必要はなく、メジャーバージョンアップのタイミングで検討いただければ十分と考えています。

初学者への配慮について

ウィジェットはテーマからも利用できる機能であるため、PHP に不慣れなテーマ開発者にとって Attribute やクラス継承の概念は最初の壁になる可能性があります。
ただし、日本語のドキュメントやサンプルコードを充実させることで十分に対応できると考えています。具体的には、以下のような整備があれば問題ないかと思います。
またはテーマではなくプラグインからしか利用できない形式にするなども考慮する必要があります。

  • 最小構成のウィジェットクラスのサンプル
  • 既存テンプレート方式との対応関係を示した移行ガイド
  • よくあるユースケースごとのリファレンス

備考

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions