EC-CUBE4 Entity PHP Trait 定数

EC-CUBE4でEntityに項目を追加するときは、本体のクラスを触らずCustomize配下のTraitに書くのが原則です。ここで困るのが、種別や区分のように「取りうる値が決まっている項目」を追加する場合です。値の文字列をコードのあちこちに書かないよう定数にしたいのですが、PHP 8.1以前ではTraitに定数を書けません。対処は、app/Customize/Common/Constant.phpに定数クラスを作って定数をそこに置き、項目本体とgetter・setterはTraitに残すことです。本体のEccube\Common\Constantに追記する方法もありますが、本体ファイルを触らずに済むCustomize側の定数クラスを勧めます。

Traitに定数を書くと出るエラー

PHP 7.4.33で確認したエラーです。構文解析の段階で止まるので、そのファイルを読み込むすべての画面が500になります。

PHP Fatal error:  Traits cannot have constants

Traitの定数はPHP 8.2で使えるようになりました(PHPマニュアル)。EC-CUBE 4.0と4.1はPHP 7.3以上で動くサイトが多いので、この制約に当てはまります。

定数の置き場所は3択

  • 本体のEntityに直接書く: 動きますが、本体ファイルを変えるとproxyの再生成が必要になり、EC-CUBE本体の更新時に差分の衝突も起きます。
  • 本体のEccube\Common\Constantに追記する: EC-CUBE本来の定数と並べて置けますが、これも本体ファイルの改変です。本体を更新するたびに差分を持ち越す必要があります。
  • Customize\Common\Constantを新設する: app/Customize/Common/Constant.phpにプロジェクト固有の定数を集めます。本体を一切触らず、名前空間Customize\composer.jsonapp/CustomizeにPSR-4対応済みなので、ファイルを置くだけで読み込まれます。

私は最初に本体のEntityへ直接書き、次に本体のConstantへ移しました。どちらも動きますが、本体ファイルへの変更が残る点は同じです。カスタマイズはCustomize配下で完結させるというEC-CUBE4の原則に戻ると、定数クラスもCustomize側に置くのが一貫しています。

定数クラスとTraitの役割分担

種別項目に関わるコードは2か所に分けます。定数クラスには、取りうる値と、その一覧を置きます。Traitには列の定義とgetter・setterを置きます。setterでは、一覧に無い値が渡されたときに既定値へ置き換えます。CSV登録で想定外の文字列が入る場合や、項目追加前の古いデータで値が空の場合があるためです。

// app/Customize/Common/Constant.php
namespace Customize\Common;

class Constant
{
    // 種別項目の取りうる値
    const CUSTOM_TYPE_DEFAULT = 'default';
    const CUSTOM_TYPE_SPECIAL = 'special';
    const CUSTOM_TYPES = [
        self::CUSTOM_TYPE_DEFAULT,
        self::CUSTOM_TYPE_SPECIAL,
    ];
}

// app/Customize/Entity/ProductTrait.php
use Customize\Common\Constant;

public function getCustomType(): string
{
    // 項目追加前の古いデータは値が空なので、既定値として扱う
    return $this->custom_type ?: Constant::CUSTOM_TYPE_DEFAULT;
}

public function setCustomType(?string $type): self
{
    // 一覧に無い値が渡されたら既定値に置き換える
    $this->custom_type = in_array($type, Constant::CUSTOM_TYPES, true)
        ? $type
        : Constant::CUSTOM_TYPE_DEFAULT;

    return $this;
}

種別項目は管理画面で選ばせることになるので、フォームの選択肢の値にも同じ定数を使います。値の定義が定数クラスの1か所にまとまり、あとで種別を増やすときは定数クラスと選択肢の表示名だけを変えれば済みます。

実装後は、既定値が返ること、値を切り替えて保存できること、一覧に無い値が既定値に置き換わることをコマンドラインから確認し、編集画面が200で表示されることまで確認してください。DBの列定義はeccube:schema:update --dump-sqlで差分が出ないことを確認します。

日本発!ECオープンプラットフォーム「EC-CUBE」 EC-CUBEゴールドパートナー EC-CUBEは株式会社イーシーキューブの商標です

EC-CUBEに関するお問い合わせ


    [重要]現在公式にセキュリティサポートが切れていないPHPは8.1以上、MySQLは8.0以上で、対応しているEC-CUBEバージョンは4.2以上です。古いEC-CUBEを使っている方は適切なタイミングでバージョンアップをご検討ください。

    EC-CUBEバージョンアップ