Entityについて説明していきます。
Entityの定義
Entityとは、データを扱うクラスです。
本体Entity:ドキュメントルート/src/Eccube/Entity
基本的には、データベースの各テーブルを定義し使用していきます。
関連するテーブルの情報を定義し「スキーマ更新コマンド」でDBへ更新も可能です。
bin/console doctrine:schema:update --dump-sql --force
商品クラスで解説
テーブル定義
/**
* Product
* ↓ これがないとクラス名でテーブルが作成される
* @ORM\Table(name="dtb_product")
* ↓ クラス階層ごとに1つのテーブルを作成します
* @ORM\InheritanceType("SINGLE_TABLE")
* ↓ テーブルの識別用カラム
* @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255)
* ↓ サービスの依存関係がないならコールバックの設定をした方が良いとのこと
* @ORM\HasLifecycleCallbacks()
* ↓ Repositoryの読込み設定
* @ORM\Entity(repositoryClass="Eccube\Repository\ProductRepository")
*/
class Product extends \Eccube\Entity\AbstractEntity
カラム定義
* @ORM\Column(name="id", type="integer", options={"unsigned":true})
* @ORM\Column(name="name", type="string", length=255)
* @ORM\Column(name="create_date", type="datetimetz")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\OneToMany(targetEntity="Eccube\Entity\ProductImage", mappedBy="Product", cascade={"remove"})
* @ORM\ManyToOne(targetEntity="Eccube\Entity\Member")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="creator_id", referencedColumnName="id")
* })
定数やメソッドも追加可能
// 編集不可ステータス
const UNEDITABLE_STATUS = [
self::PENDING,
self::PROCESSING,
self::CREDIT_SLIP,
];
/**
* 銀行支払いかチェック
* @return bool
*/
public function isBankPayment() {
return $this->getId() == Payment::BANK_PAYMENT ? true:false;
}
データ登録の流れ
- 登録対象Entityの取得 $Product = new Product
- $Product->setName = ‘テスト商品’
- 永続化登録設定 $this->entityManager->persist($Product)
- 登録処理 $this->entityManager->flush($Product)
実際のDBへ登録されるタイミングは、エラーがなく正常終了してテンプレートにいくタイミング。
Entityをカスタマイズしたい場合
src配下のEntity本体ソースは、アプデで影響が出る可能性があるので、
カラムやメソッドを追加したい場合
CustomizeでTraitを使用し拡張する
この場合は、スキーマ更新コマンドでdtb_categoryへslugカラムが追加される。
更新手順↓
proxy更新→キャッシュクリア→スキーマ更新コマンド
<?php
namespace Customize\Entity;
use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation\EntityExtension;
/**
* @EntityExtension("Eccube\Entity\Category")
*/
trait CategoryTrait
{
/**
* @var string
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $slug;
/**
* @return string|null
*/
public function getSlug(): ?string
{
return $this->slug;
}
/**
* @param string|null $slug
* @return $this
*/
public function setSlug(?string $slug): self
{
$this->slug = $slug;
return $this;
}
}
定数を使用したい場合
元のEntityを継承して使用する
<?php
namespace Customize\Entity\Master;
use Eccube\Entity\Master\OrderStatus as BaseEntity;
if (!class_exists('Customize\Entity\Master\OrderStatus')) {
/** 親クラスの定数宣言を拡張する目的に作成しています */
class OrderStatus extends BaseEntity {
/** 入金待ち */
const PAY_WAIT = 2;
// 編集不可ステータス
const UNEDITABLE_STATUS = [
self::PENDING,
self::PROCESSING,
self::CREDIT_SLIP,
];
}
}
使用したいファイルで、useして使用する
use Customize\Entity\Master\OrderStatus;
既存の他のTrait読み込み
下記プログラムでgetFullName()が使用可能となる
<?php
namespace Customize\Entity;
use Eccube\Annotation\EntityExtension;
use Eccube\Entity\NameTrait;
/**
* @EntityExtension("Eccube\Entity\Customer")
*/
trait CustomerTrait
{
use NameTrait;
}
src/Eccube/Entity/NameTrait.php
<?php
namespace Eccube\Entity;
trait NameTrait
{
public function getFullName()
{
return (string) $this->name01.' '.$this->name02;
}
public function getFullNameKana()
{
return (string) $this->kana01.' '.$this->kana02;
}
}
以前ハマった対応があったので紹介します。
初期表示データ取得できない
カスタマイズ中に発生した問題です。
EC-CUBE4は基本的にDoctrineを使用しています。
データベースをオブジェクト化した物で、都度データベースにアクセスしないでデータの取得や加工が行えます。
なぜこの状態になったか?
取得できなかったデータ
※わかりやすくEC-CUBEデフォルトのテーブルで説明します。
要件:カートの情報をデータ登録直後に一覧ページに表示したい。
関連するテーブルは、dtb_cartとdtb_cart_itemの2種類です。
パターン1
- dtb_cartへEntityで登録+永続化+フラッシュ
- dtb_cart_itemへEntityで登録+永続化+フラッシュ
- findByでリスト取得して、テンプレートへ
パターン2
- dtb_cartへEntityで登録+永続化+フラッシュ
- dtb_cart_itemへEntityで登録+永続化+フラッシュ
- テンプレートでfindByしてリスト取得
上記でうまくいかなかったです。
結局なんだったかと言うと、
リレーションが貼ってあるので、cart→cart_itemの順で登録
cartは最新の登録データは持っているが、紐づくcart_itemは後から登録されるので
cartのEntityに、cart_itemの最新情報が紐づいていない状態
cartのEntityを更新する
$this->entityManager->refresh(XXX);
XXXは、更新するEntityオブジェクト
$this->entityManager->refresh($cart);
これで解決!
コメント