この記事では、以下のように2つのテーブルを関連付ける方法を紹介します。
「dtb_product_class」テーブルでは、以下のように「dtb_product」や「dtb_sale_type」などのテーブルとidで関連づいている。
「dtb_product_class」テーブルの「product_id」をクリックすると、以下のように関連づいたレコードが表示される。
デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については 以下記事 で解説しています。
カスタマイズ後は、デバッグモードの解除を忘れないように。
テーブル連携は、所有側と非所有側の両エンティティに関連性を定義する
EC-CUBEのフレームワークであるSymfonyでは、Doctrine ORMを使用することでエンティティ間に関連性(リレーションシップ)を定義できます。
例として、メーカーの基本情報を管理するMaker
エンティティと、メーカーの詳細情報を管理する MakerInfo
エンティティの間に関連性を持たせる場合、以下の2つの関係が考えられます。
- ManyToOne
-
1つの
MakerInfo
は、1つのMaker
に属します。 - OneToMany
-
1つの
Maker
は複数のMakerInfo
を持つことができます。
この関連性をDoctrineで表現する際、2つのエンティティのどちらが “所有者” であるかを明示します。
“所有者” は、実際にデータベースのテーブルに外部キーとしての関連性を持つ側です。
所有権を明示するためには、 mappedBy
と inversedBy
という属性を記述します。
- mappedBy
-
非所有側で使用。
属性値は、所有側のエンティティ内のプロパティ名を記述。 - inversedBy
-
所有側で使用。
属性値は、非所有側のエンティティ内のプロパティ名を記述。
このケースでは、
MakerInfo
エンティティがManyToOne
という関係で所有側Maker
エンティティはOneToMany
という関係で非所有側
したがって、MakerInfo
エンティティの ManyToOne
アノテーションには inversedBy
属性を使用し、その値は Maker
エンティティ内の関連プロパティ名(基本的には配列形式のプロパティ)を指定します。
例えば、Maker
エンティティ内で private $MakerInfos;
というプロパティ名を使用する場合、MakerInfo
エンティティの ManyToOne
アノテーションの inversedBy
属性の値は MakerInfos
となります。
以下、実際の手順やコードを公開します。
実例)「dtb_maker」と「dtb_maker_info」テーブルを作成し、連携させる
メーカー名などを管理する「dtb_maker」と、各メーカーに紐づいた情報を管理する「dtb_maker_info」を作成します。
「dtb_maker_info」では、各レコードにmaker_idを割り振ることで「dtb_maker」と関連付けます。
テーブルの作成については こちらの記事 にて紹介していますので、本記事では連携部分を中心に解説します。
- メーカーの基本情報を管理する
Maker
エンティティを作成し、サーバーにアップ。 - メーカーの詳細情報を管理する
MakerInfo
エンティティを作成し、サーバーにアップ。 - サーバーにSSH接続し、SQLを実行する。
Makerエンティティを作成する
以下のコードを記載した Maker
エンティティを作成し、「app/Customize/Entity」にアップします。
エンティティの連携は、コードの後半部分で定義しています。
<?php
namespace Customize\Entity;
use Eccube\Entity\AbstractEntity;
use Doctrine\ORM\Mapping as ORM;
/**
* 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();
}
// MakerInfoエンティティの連携
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Customize\Entity\MakerInfo", mappedBy="maker")
*/
private $makerInfos;
/**
* Makerに新しいMakerInfoを追加するメソッド
*
* @param \Customize\Entity\MakerInfo $makerInfo
*
* @return Maker
*/
public function addMakerInfo(MakerInfo $makerInfo)
{
$this->makerInfos[] = $makerInfo;
return $this;
}
/**
* 特定のMakerInfoをMakerから削除するメソッド
*
* @param \Customize\Entity\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;
}
}
MakerInfo
エンティティとの連携は、アノテーションで以下のようなことが示されています。
- @ORM\OneToMany
-
Maker
とMakerInfo
の間の関係が「一対多」であることを示します。
つまり、一つのMaker
は複数のMakerInfo
を持つことができます。 - targetEntity=”Customize\Entity\MakerInfo”
-
連携対象となるエンティティを示します。
- mappedBy=”maker”
-
MakerInfo
側にmaker
という名前のプロパティが存在し、そのプロパティを通じてこの関係が管理されていることを示します。
加えて、関連エンティティを操作するためのメソッドも定義しています。
これらのメソッドを使って、Maker
とMakerNote
の間の関係を管理できます。
- addMakerInfo
-
新しい
MakerInfo
をMaker
に関連付けるためのメソッド。 - removeMakerInfo
-
既存の
MakerInfo
の関連付けを解除するためのメソッド。 - getMakerInfos
-
Maker
に関連付けられているすべてのMakerInfo
を取得するためのメソッド。
MakerInfoエンティティを作成する
続いて、以下のコードを記載した MakerInfo
エンティティを作成し、「app/Customize/Entity」にアップします。
<?php
namespace Customize\Entity;
use Eccube\Entity\AbstractEntity;
use Doctrine\ORM\Mapping as ORM;
/**
* MakerInfo
*
* @ORM\Table(name="dtb_maker_info")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255)
* @ORM\HasLifecycleCallbacks()
* @ORM\Entity(repositoryClass="Customize\Repository\MakerInfoRepository")
*/
class MakerInfo extends AbstractEntity
{
/**
* 一意の識別子(ID)
*
* @var integer
*
* @ORM\Column(name="id", type="integer", options={"unsigned":true})
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* このMakerInfoが関連付けられているMakerエンティティ
*
* @var \Customize\Entity\Maker
*
* @ORM\ManyToOne(targetEntity="Customize\Entity\Maker", inversedBy="makerInfos")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="maker_id", referencedColumnName="id")
* })
*/
private $maker;
/**
* メーカーに関する追加情報
*
* @var string|null
*
* @ORM\Column(name="info", type="string", length=4000)
*/
private $info;
/**
* エンティティが作成された日時
*
* @var \DateTime
*
* @ORM\Column(name="create_date", type="datetimetz")
*/
private $create_date;
/**
* エンティティが最後に更新された日時
*
* @var \DateTime
*
* @ORM\Column(name="update_date", type="datetimetz")
*/
private $update_date;
/**
* IDを取得します。
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Makerエンティティを設定します。
*
* @param \Customize\Entity\Maker|null $maker
*
* @return MakerInfo
*/
public function setMaker(Maker $maker = null)
{
$this->maker = $maker;
return $this;
}
/**
* Makerエンティティを取得します。
*
* @return \Customize\Entity\Maker|null
*/
public function getMaker()
{
return $this->maker;
}
/**
* メーカー情報を設定します。
*
* @param string|null $info
*
* @return MakerInfo
*/
public function setInfo($info = null)
{
$this->info = $info;
return $this;
}
/**
* メーカー情報を取得します。
*
* @return string|null
*/
public function getInfo()
{
return $this->info;
}
/**
* 作成日を設定します。
*
* @param \DateTime $createDate
*
* @return MakerInfo
*/
public function setCreateDate($createDate)
{
$this->create_date = $createDate;
return $this;
}
/**
* 作成日を取得します。
*
* @return \DateTime
*/
public function getCreateDate()
{
return $this->create_date;
}
/**
* 更新日を設定します。
*
* @param \DateTime $updateDate
*
* @return MakerInfo
*/
public function setUpdateDate($updateDate)
{
$this->update_date = $updateDate;
return $this;
}
/**
* 更新日を取得します。
*
* @return \DateTime
*/
public function getUpdateDate()
{
return $this->update_date;
}
}
Maker
エンティティとの連携は、アノテーションで以下のようなことが示されています。
- @ORM\ManyToOne
-
MakerInfo
はMaker
と「多対一」の関係にあることを示します。
つまり、一つのMaker
は複数のMakerInfo
を持つことができます。 - targetEntity=”Customize\Entity\Maker”
-
連携対象となるエンティティを示します。
- inversedBy=”makerInfos”
-
Maker
側には、この関連を逆向きに参照するプロパティmakerInfos
が存在することを示します。 - @ORM\JoinColumns
-
MakerInfo
テーブルのmaker_id
カラムは、Maker
テーブルのid
カラムと結合されています。
サーバーに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
このコマンド実行後、問題がなければテーブルが新規作成(更新)されているはずです。
まとめ & 次のステップ
以上、複数のテーブルを関連付けて管理する方法を紹介しました。
本記事の例のように、テーブル同士を連携して管理したい場面は多々あると思いますので、ぜひ応用してもらえればと思います。
既存テーブルへの連携や、フォーム追加方法も以下に公開しているので、合わせてご覧ください。