【EC-CUBE 4】既存テーブルと新規テーブルを連携する方法

以下記事の応用編として、デフォルトで用意されている商品テーブル(dtb_product)と、新規に作成したメーカーテーブル(dtb_maker)を関連付けて管理する方法について紹介します。

【動作環境】
EC CUBEのバージョン:4.2.1
サーバー:Xserver

開発前にデバッグモードの設定をお薦めします

デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については 以下記事 で解説しています。

カスタマイズ後は、デバッグモードの解除を忘れないように。

目次

テーブル連携は、所有側と非所有側の両エンティティに関連性を定義する

EC-CUBEのフレームワークであるSymfonyでは、Doctrine ORMを使用することでエンティティ間に関連性(リレーションシップ)を定義できます。

本実装例では、商品情報を管理する Productエンティティと、メーカー情報を管理するMaker エンティティに以下の関係性を持たせます。

ManyToOne

1つの Product は、1つの Maker に属します。

OneToMany

1つの Maker は複数の Product を持つことができます。

上記に加え、所有権を明示するために mappedByinversedByという属性を記述します。

mappedBy

非所有側( Makerエンティティ)で使用。
属性値は、所有側のエンティティ内のプロパティ名を記述。

inversedBy

所有側( Productエンティティ)で使用。
属性値は、非所有側のエンティティ内のプロパティ名を記述。

以下、実際の手順やコードを公開します。

実例)「dtb_product」と「dtb_maker」を連携させる

EC-CUBE側で用意されている「dtb_product」に”maker_id” というカラムを追加し、「dtb_maker」の”id”と紐づけます。こうすることで、1つの商品に1つのメーカーIDが割り当てられ、「dtb_maker」に保存されているメーカー情報と関連付けられます。

なお、テーブルの新規作成方法や既存テーブルに新しいカラムを追加する方法については、以下記事をご覧ください。

全体の流れ
  1. 前回作成済の Makerエンティティに、Productエンティティとの連携を定義する。
  2. Productエンティティの拡張ファイルである ProductTraitに、Makerエンティティとの連携を定義する。
  3. サーバーにSSH接続し、SQLを実行する。
  4. 【発展】管理画面からMekerエンティティの登録ができるようにする。
STEP

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

MakerProductの間の関係が「一対多」であることを示します。
つまり、一つの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

新しいProductMakerに関連付けるためのメソッド。

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;
    }
}
STEP

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

ProductMaker と「多対一」の関係にあることを示します。
つまり、一つの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;
    }
}
STEP

サーバーに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)が追加されているはずです。

STEP

【発展】管理画面からMakerエンティティの登録ができるフォームを生成する

Productテーブル(dtb_product)拡張後は、以下のように管理画面の商品登録から、Makerエンティティを追加できるようにするとより便利です。

「メーカー」というフォームを作り、メーカー名を選ぶことでMakerエンティティをテーブルに保存できる。

詳しくは以下記事で紹介しているので、本記事と合わせてカスタマイズしてみてください!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次