LoginSignup
6
10

More than 5 years have passed since last update.

[CakePHP3]belongsToMany(多対多)のデータの保存方法

Last updated at Posted at 2019-01-17

  

この記事でわかること

  • belongsToManyの使い方
  • belongsToManyな関係のデータの保存方法

前提

想定

塾講師の管理システムを作るとします。
今回実装したい機能は、講師の担当教科を設定できるようにすることです。
例:ジョージ先生は数学、物理を担当している。

使用するテーブル

  • teachers:講師情報(名前など)を管理するテーブル
  • subjects:教科テーブル(nameカラムに「数学」や「英語」などが入る)
  • teachers_subjects:講師がどの教科を教えることができるのかを保持しているテーブル
CREATE TABLE teachers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50),
    created DATETIME,
    modified DATETIME
);

CREATE TABLE subjects (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    created DATETIME,
    modified DATETIME
);

CREATE TABLE teachers_subjects (
    teacher_id INT NOT NULL,
    subject_id INT NOT NULL,
    PRIMARY KEY (teacher_id, subject_id),
    FOREIGN KEY subject_key(subject_id) REFERENCES subjects(id),
    FOREIGN KEY teacher_key(teacher_id) REFERENCES teachers(id)
);

belongsToManyについて

belongsToManyは “Teachers belongsToMany Subjects” (先生が多くの科目に属する) ということになります。
belongsToMany アソシエーションでは三つのデータベーステーブルが必要です。
今回で言えば、 teachers 、 subjects および teachers_subjects で、
結合(中間)テーブルは、関連する二つのテーブルの名前をアンダースコアーで結びつけるという規約があります。

こんな感じでデータを保持します。

  • ジョージ先生は数学、物理を担当している。
  • ロレイン先生は国語、英語、歴史を担当している。

teachersテーブル

id name
1 ジョージ
2 ロレイン

subjectsテーブル

id name
1 数学
2 国語
3 英語
4 歴史
5 地理
6 物理
7 化学

teachers_subjectsテーブル

id teacher_id subject_id
1 1 1
2 1 6
3 2 2
4 2 3
5 2 4

アソシエーション

両方のモデルの中で belongsTo アソシエーションを定義することができます。

src/Model/Table/TeachersTable.php
class TeachersTable extends Table
{
    public function initialize(array $config)
    {
        $this->belongsToMany('Subjects');
    }
}

src/Model/Table/SubjectsTable.php
class SubjectsTable extends Table
{
    public function initialize(array $config)
    {
        $this->belongsToMany('Teachers');
    }
}

belongsToManyな関係のデータの保存方法

では実際に、担当科目を設定できるようにしていきます。
まず、TeachersからSubjectsのデータを保存できるようにします。

src/Model/Entity/Teacher.php

class Teacher extends Entity
{
    protected $_accessible = [
        'name' => true,
        'subjects' => true //←これを忘れると保存できないので注意
    ];
}

講師を追加するためのaddアクションです。
本来はフォームから受け取ったデータを保存するべきですが割愛します。

src/Controller/TeachersController.php

<?php
namespace App\Controller;

class TeachersController extends AppController
{
    public function add()
    {
        $data = [
            'name' => 'ジョージ',
            'subjects' => [
                ['subject_name' => '数学'],
                ['subject_name' => '物理']
            ]
        ];
        $teachers = TableRegistry::get('Teachers');
        $teacher = $teachers->newEntity($data, [
            'associated' => ['Subjects'],
        ]);
        $this->Teachers->save($teacher);

        return $this->redirect(['action' => 'index']);
    }
}

これだけで講師(teachers)、教科(subjects)、その講師が担当できる教科(teachers_subjects)が一度に保存できました。
なかなか便利ですね〜
今まで、teachers_subjectsのような中間テーブルを手動で保存していたので、これからはもっとスマートに書けそうです。

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10