BeginnerEngineerBlog
中の人
中の人

【ECCUBE4 symfony】traitで追加したentityフィールドにインデックスを貼りたい

公開: 2023-09-05 01:03
更新: 2023-10-19 01:18
436
ECCUBE4.2 symfony5.x trait entity index
ECCUBE4でtraitで追加したフィールドにインデックスを貼りたくて調べたらドンピシャな記事に助けられましたので紹介します。

こんにちは!

中の人です

eccube4系でデータベースを拡張するとき、traitで拡張することがベーシックになると思いますが、拡張して追加したフィールドにインデックス貼りたいぜって時ありますよね
最近やり方わかったので紹介します!

環境
ECCUBE4.2
symfony5.4
mysql5.7

symfonyのentityでindexを貼るやり方


多分ですが、symfonyでテーブルを作成する際、doctrineというORMを利用してentityによってテーブルなりフィールドなりを追加することになると思いますが、その際indexを貼る場合


こちらの回答にある通り

<?php
/**
 * @Entity
 *                                    👇これ
 * @Table(name="ecommerce_products",indexes={
 *     @Index(name="search_idx", columns={"name", "email"})
 * })
 */
class ECommerceProduct
{
}

基本的にテーブル作成時にしかindexを貼ることできないみたいなんですね

eccube4はすでにテーブルが作成されてて、traitで拡張するしかないんですよね(本体ソース書き換えればできます)


migrationでインデックス貼ればいいじゃん


ね!

なんですが、entityでテーブルを作成したりフィールド追加したりする時に

bin/console doctrin:schema:update --force

というコマンド打つと思うのですが、これやると、migrationでインデックス貼ってると解除されちゃうんですよね


で結局どうやるん


ということで参考にした記事は以下になります


yunさんもAlex Kuninさんもありがとうございます!
という感じで、以下のようにeventlistenerを追加するとうまいことindex貼ることできました。

traitを作成



📁 ec-cube/app/Customize/Entity/MyTrait.php

<?php
namespace Customize\Entity;

use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation\EntityExtension;

/**
 * @EntityExtension("Eccube\Entity\ProductClass")
 */
trait MyTrait
{
    /**
     * @var string
     * @ORM\Column("some_field", type="string")
     */
    protected $someField;

    public function setSomeField(string $someField): self
    {
        $this->someField = $someField;
        return $this;
    }

    public function getSomeField(): string
    {
        return $this->someField;
    }
}

フィールド名や拡張するテーブルは適宜変更してください


EventListenerを作成


📁 ec-cube/app/Customize/EventListener/MyEntityListener.php

<?php
namespace Customize\EventListener;

use Customize\Entity\MyTrait;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;

class MyEntityListener implements EventSubscriber
{
    public function getSubscribedEvents()
    {
        return [
            'loadClassMetadata',
        ];
    }

    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $cm = $eventArgs->getClassMetadata();
        $class = $cm->getName();
        $uses = class_uses($class);// 👈 traitを作成している場合、この$usesに作成したtraitのpath?が入ってくる

        if (in_array(MyTrait::class, $uses)) {
            $cm->table['indexes'][] = [// 👈 これでインデックスを追加することができる
                'columns' => [
                    'some_field',
                ],
            ];
        }
    }
}


このイベントは、正直よくわかってませんが、上記の

bin/console doctrin:schema:update --force

これが実行された際に呼び出されるイベントです

ちなみにですが、拡張したいテーブルのクラスを拡張するためのtraitがないとifの条件の中には入ってきません。
なので、既存のフィールドにインデックスを追加したい場合は、空のtraitを作成してifを同じように書いたら動作しました。

すげー


ちなみに


参考にさせていただいたDoctrine+Symfony: adding indexes to fields defined in traits | by Alex Kunin | Mediumには、services.yamlにserviceを登録する記述がありましたが、私の環境では特に書かなくても動作しました(というかservices.yamlよく仕様わからないし真似て書いたけどエラーが出ました)
バージョン?の違い?なんでしょうか?
よくわかりませんが動いたのでservices.yamlはいじりませんでした。

終わりに


本当ネットで情報発信してくれる方に感謝です!
special thanks to Alex Kunin!!

ということで

お疲れ様でした
0
0
0
0
通信エラーが発生しました。
【広告】
似たような記事