以下記事の応用編として、デフォルトで用意されている商品テーブル(dtb_product)と、新規に作成したメーカーテーブル(dtb_maker)を関連付けて管理する方法について紹介します。
デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については 以下記事 で解説しています。
カスタマイズ後は、デバッグモードの解除を忘れないように。
テーブル連携は、所有側と非所有側の両エンティティに関連性を定義する
EC-CUBEのフレームワークであるSymfonyでは、Doctrine ORMを使用することでエンティティ間に関連性(リレーションシップ)を定義できます。
本実装例では、商品情報を管理する Product
エンティティと、メーカー情報を管理するMaker
エンティティに以下の関係性を持たせます。
- ManyToOne
-
1つの
Product
は、1つのMaker
に属します。 - OneToMany
-
1つの
Maker
は複数のProduct
を持つことができます。
上記に加え、所有権を明示するために mappedBy
と inversedBy
という属性を記述します。
- mappedBy
-
非所有側(
Maker
エンティティ)で使用。
属性値は、所有側のエンティティ内のプロパティ名を記述。 - inversedBy
-
所有側(
Product
エンティティ)で使用。
属性値は、非所有側のエンティティ内のプロパティ名を記述。
以下、実際の手順やコードを公開します。
実例)「dtb_product」と「dtb_maker」を連携させる
EC-CUBE側で用意されている「dtb_product」に”maker_id” というカラムを追加し、「dtb_maker」の”id”と紐づけます。こうすることで、1つの商品に1つのメーカーIDが割り当てられ、「dtb_maker」に保存されているメーカー情報と関連付けられます。
なお、テーブルの新規作成方法や既存テーブルに新しいカラムを追加する方法については、以下記事をご覧ください。
- 前回作成済の
Maker
エンティティに、Product
エンティティとの連携を定義する。 Product
エンティティの拡張ファイルであるProductTrait
に、Maker
エンティティとの連携を定義する。- サーバーにSSH接続し、SQLを実行する。
- 【発展】管理画面からMekerエンティティの登録ができるようにする。
MakerエンティティにProductエンティティとの連携を定義
以下のコードを Maker
エンティティを追記し、「app/Customize/Entity」にアップします。
- useステートメントの追加
-
use Eccube\Entity\Product;
- エンティティ連携のconstructの追加
-
$this->products = new \Doctrine\Common\Collections\ArrayCollection();
- Productエンティティの連携
-
/** * @var \Doctrine\Common\Collections\Collection * * @ORM\OneToMany(targetEntity="Eccube\Entity\Product", mappedBy="maker") */ private $products;
- @ORM\OneToMany
-
Maker
とProduct
の間の関係が「一対多」であることを示します。
つまり、一つのMaker
は複数のProduct
を持つことができます。 - targetEntity=”Eccube\Entity\Product”
-
連携対象となるエンティティを示します。
- mappedBy=”maker”
-
Product
側にmaker
という名前のプロパティが存在し、そのプロパティを通じてこの関係が管理されていることを示します。
- 基本メソッド(add, remove, get)の設定
-
/** * @param Product $product * * @return Maker */ public function addProduct(Product $product) { $this->products[] = $product; return $this; } /** * @param Product $product * * @return boolean */ public function removeProduct(Product $product) { return $this->products->removeElement($product); } /** * @return \Doctrine\Common\Collections\Collection */ public function getProducts() { return $this->products; }
- addProduct
-
新しい
Product
をMaker
に関連付けるためのメソッド。 - removeProduct
-
既存の
Product
の関連付けを解除するためのメソッド。 - getProduct
-
Maker
に関連付けられているすべてのProduct
を取得するためのメソッド。
追記・修正された Makerエンティティ全コードを見る
<?php
namespace Customize\Entity;
use Eccube\Entity\AbstractEntity;
use Doctrine\ORM\Mapping as ORM;
use Customize\Entity\MakerInfo;
use Eccube\Entity\Product;
/**
* Maker
*
* @ORM\Table(name="dtb_maker")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255)
* @ORM\HasLifecycleCallbacks()
* @ORM\Entity(repositoryClass="Customize\Repository\MakerRepository")
*/
class Maker extends AbstractEntity
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", options={"unsigned":true})
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* メーカーの一意識別ID(自動連番)です。
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*
* メーカーの名前です。
*/
private $name;
/**
* @var string|null
*
* @ORM\Column(name="code", type="string", length=8, nullable=true)
*
* メーカーのコードです。null(未入力)も許容されます。
*/
private $code;
/**
* @var \DateTime
*
* @ORM\Column(name="create_date", type="datetimetz")
*
* メーカー情報の作成日時です。
*/
private $create_date;
/**
* @var \DateTime
*
* @ORM\Column(name="update_date", type="datetimetz")
*
* メーカー情報の最終更新日時です。
*/
private $update_date;
/**
* Get id.
*
* @return int
*
* メーカーのIDを取得します。
*/
public function getId()
{
return $this->id;
}
/**
* Set name.
*
* @param string $name
*
* @return Maker
*
* メーカーの名前を設定します。
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name.
*
* @return string
*
* メーカーの名前を取得します。
*/
public function getName()
{
return $this->name;
}
/**
* Set code.
*
* @param string|null $code
*
* @return Maker
*
* メーカーのコードを設定します。null(未入力)も許容されます。
*/
public function setCode($code = null)
{
$this->code = $code;
return $this;
}
/**
* Get code.
*
* @return string|null
*
* メーカーのコードを取得します。
*/
public function getCode()
{
return $this->code;
}
/**
* Set createDate.
*
* @param \DateTime $createDate
*
* @return Maker
*
* メーカー情報の作成日時を設定します。
*/
public function setCreateDate($createDate)
{
$this->create_date = $createDate;
return $this;
}
/**
* Get createDate.
*
* @return \DateTime
*
* メーカー情報の作成日時を取得します。
*/
public function getCreateDate()
{
return $this->create_date;
}
/**
* Set updateDate.
*
* @param \DateTime $updateDate
*
* @return Maker
*
* メーカー情報の最終更新日時を設定します。
*/
public function setUpdateDate($updateDate)
{
$this->update_date = $updateDate;
return $this;
}
/**
* Get updateDate.
*
* @return \DateTime
*
* メーカー情報の最終更新日時を取得します。
*/
public function getUpdateDate()
{
return $this->update_date;
}
// エンティティ連携のconstruct
public function __construct()
{
$this->makerInfos = new \Doctrine\Common\Collections\ArrayCollection();
$this->products = new \Doctrine\Common\Collections\ArrayCollection();
}
// MakerInfoエンティティの連携
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Customize\Entity\MakerInfo", mappedBy="maker")
*/
private $makerInfos;
// Productエンティティの連携
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Eccube\Entity\Product", mappedBy="maker")
*/
private $products;
/**
* Makerに新しいMakerInfoを追加するメソッド
*
* @param MakerInfo $makerInfo
*
* @return Maker
*/
public function addMakerInfo(MakerInfo $makerInfo)
{
$this->makerInfos[] = $makerInfo;
return $this;
}
/**
* 特定のMakerInfoをMakerから削除するメソッド
*
* @param MakerInfo $makerInfo
*
* @return boolean
*/
public function removeMakerInfo(MakerInfo $makerInfo)
{
return $this->makerInfos->removeElement($makerInfo);
}
/**
* 現在のMakerに関連付けられているすべてのMakerInfoを取得するメソッド
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getMakerInfos()
{
return $this->makerInfos;
}
/**
* Makerに新しいProductを追加するメソッド
*
* @param Product $product
*
* @return Maker
*/
public function addProduct(Product $product)
{
$this->products[] = $product;
return $this;
}
/**
* 特定のProductをMakerから削除するメソッド
*
* @param Product $product
*
* @return boolean
*/
public function removeProduct(Product $product)
{
return $this->products->removeElement($product);
}
/**
* 現在のMakerに関連付けられているすべてのProductを取得するメソッド
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
}
ProductTraitにMakerエンティティとの連携を定義
Product
エンティティの拡張ファイルである ProductTrait
に以下コードを追記し、「app/Customize/Entity」にアップします。
- useステートメントの追加
-
use Customize\Entity\Maker;
- Makerエンティティの連携
-
/** * @var Maker * * @ORM\ManyToOne(targetEntity="Customize\Entity\Maker", inversedBy="products") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="maker_id", referencedColumnName="id") * }) */ private $maker;
- @ORM\ManyToOne
-
Product
はMaker
と「多対一」の関係にあることを示します。
つまり、一つのMaker
は複数のProduct
を持つことができます。 - targetEntity=”Customize\Entity\Maker”
-
連携対象となるエンティティを示します。
- inversedBy=”products”
-
Maker
側には、この関連を逆向きに参照するプロパティproducts
が存在することを示します。 - @ORM\JoinColumns
-
Product
テーブルのmaker_id
カラムは、Maker
テーブルのid
カラムと結合されています。
- 基本メソッド(set,get)の設定
-
/** * @param Maker|null $maker * * @return $this */ public function setMaker(Maker $maker = null) { $this->maker = $maker; return $this; } /** * @return Maker|null */ public function getMaker() { return $this->maker; }
追記・修正された ProductTrait全コードを見る
<?php
namespace Customize\Entity;
use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation\EntityExtension;
use Customize\Entity\Maker;
/**
* 拡張したいエンティティ(ここでは「Product」エンティティ)を指定。
*
* @EntityExtension("Eccube\Entity\Product")
*/
trait ProductTrait
{
/**
* @var Maker
*
* @ORM\ManyToOne(targetEntity="Customize\Entity\Maker", inversedBy="products")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="maker_id", referencedColumnName="id")
* })
*/
private $maker;
/**
* 製品の生産地域として、$production_areaを用意。
* プロパティ名(name)、データ型(type)、文字数(length)、nullを許可するか(nullable)、なども合わせて指定。
*
* @var string|null
*
* @ORM\Column(name="production_area", type="string", length=255, nullable=true)
*/
private $production_area = null;
/**
* setメソッドで製品の生産地域($production_area)を保存できるようにする。
* 値が設定されなかった場合、nullに設定される。
*
* @param string|null $production_area
*
* @return $this
*/
public function setProductionArea($production_area = null)
{
$this->production_area = $production_area;
return $this;
}
/**
* getメソッドで製品の生産地域($production_area)を取り出せるようにする。
* 値が設定されていない場合、nullを返す。
*
* @return string|null
*/
public function getProductionArea()
{
return $this->production_area;
}
/**
* setメソッドで製品のメーカー($maker)を保存できるようにする。
* 値が設定されなかった場合、nullに設定される。
*
* @param Maker|null $maker
*
* @return $this
*/
public function setMaker(Maker $maker = null)
{
$this->maker = $maker;
return $this;
}
/**
* getメソッドで製品のメーカー($maker)を取り出せるようにする。
* 値が設定されていない場合、nullを返す。
*
* @return Maker|null
*/
public function getMaker()
{
return $this->maker;
}
}
サーバーにSSH接続し、SQLを実行してテーブルを生成する
2つのエンティティを追記・修正後にアップロードしたら、サーバーにSSH接続して以下コマンドを入力します。
(新規テーブルを作成する場合と手順は同じです。)
まずは以下コマンドでキャッシュを削除します。
bin/console cache:clear --no-warmup
実行すると、
[OK] Cache for the ・・・・・・・ was successfully cleared.
というような文言が表示される。
次にデータベースを更新するためのSQLコマンドを入力します。
bin/console doctrine:schema:update --dump-sql
上は確認用のコマンドで、実行する場合は「–force」を付けた以下コマンドを入力します。
bin/console doctrine:schema:update --dump-sql --force
このコマンド実行後、問題がなければProductテーブル(dtb_product)に新しいカラム(maker_id)が追加されているはずです。
【発展】管理画面からMakerエンティティの登録ができるフォームを生成する
Productテーブル(dtb_product)拡張後は、以下のように管理画面の商品登録から、Makerエンティティを追加できるようにするとより便利です。
詳しくは以下記事で紹介しているので、本記事と合わせてカスタマイズしてみてください!