Symfony ORMのリレーション設定方法

どうも皆さん初めまして、くじらシステム開発の徳嶺です。

入社して1年symfonyの開発も慣れて便利だと思ったことをメモついでに書いていこうともいます。

Web開発に関わらずデータベースを使った開発を行った場合必ず出てくるのがリレーション(関連)です。

複数のデータベースを使い、一つの情報を表示することがあるかと思います。

そこで、symfonyのORMを活用するとリレーション情報を簡単に表示、登録ができ便利なので紹介します。

参考サイト: https://symfony.com/doc/current/doctrine/associations.html

  •  初めに

Entityの用意、symfonyの公式サイトを使って説明していきます。

AppBundle\Entity\Product:
    type: entity
    table: product
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        name:
            type: string
            length: 100
        price:
            type: decimal
            scale: 2
        description:
            type: text
        category_id:
            type: integer

製品というテーブルを用意します。次にそのテーブルに関連するテーブルを用意します。

AppBundle\Entity\Category:
    type: entity
    table: category
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        name:
            type: string
            length: 100

これで、製品とカテゴリー(製品に紐づくテーブル)を用意できました。

ここまでは普段通りテーブルを作っただけです。次にリレーションをormに登録します。

  • リレーション設定
AppBundle\Entity\Product:
    # 略
  manyToOne:
      category:
          targetEntity: Category
          inversedBy: products
          joinColumn:
               name: category_id
               referencedColumnName: id

Productのcategoryプロパティにormを設定します。product.category_idとcategory.idで紐づいている状態です。

次にcategoryにもproductと紐づくためのormを設定します。

項目説明

targetEntity: 関連するEntity名

inversedBy: 関連するのEntityのプロパティ名(Productが登録されているプロパティ名

joinColumn: リレーションの項目名を記述する

name: 自身のテーブルの項目名 (プロパティ名ではなく、DBの項目名を設定する)

referencedColumnName: 関連するテーブルの項目名

App\Entity\Category:
    # 略
    oneToMany:
        products:
            targetEntity: Product
            mappedBy: category

Categoryのproductsのプロパティーにormを設定します。productのormに紐づく情報は記述しているためCategoryではそれを参照するだけで大丈夫です。

これで、リレーションの設定ができ、ProductからCategoryを自動で呼び出してくれます。またその逆でCategoryからCategoryに紐づいたProductを呼び出すことができます。

このことにより、ProductとCategoryをそれぞれ取得するコードを書くことがなくなります。(ソースがスッキリするよ!

※ただし、リレーション設定すると登録方法が若干変わります。

項目説明

targetEntity: 関連するEntity名

mappedBy: 関連するEntityのプロパティ名

  • リレーションの登録
        $product = new Product();
        $product->setName('Keyboard');
        $product->setPrice(19.99);
        $product->setDescription('Ergonomic and stylish!');

        // relates this product to the category
        $product->setCategory($category);

いままでは、category_idを設定していたところが、関連するEntityをSetしなければなりません。もし、EntityをSetせずcategory_idをSetした場合はpersist時にnullで登録されてしまいます。

 

  • まとめ
  1. ORMでリレーションを登録しておくと、コードの記述が減りソース全体がスッキリする。
  2. 関連する情報を表示する際ミスが減る(バグが減ります。)
  3. 自身Entityだけのリレーションも作成できるため階層構造をORMだけで実現できる。(いつか書くかも

ブログ書くの初めてなので、読みにくい場合はごめんなさい!

まだまだ、ORMのリレーションには色々機能があるのでまた機会があれば書いていこうと思います。

 

==========余談===============

最近Vue.jsを使って開発していますが、なかなかsymfonyとの共存が難しいですね。なにか良いサイト等あれば教えてください。

また、Vue.jsを使えばJQuery撲滅できると思ったけどどっちも一長一短あり苦戦中です。

phpカンファレンス福岡に参加できず残念です。;;

===========================