Laravel 10 入門トップページ


目次

  1. 概要
  2. プロジェクトの作成と初期設定
  3. 一対多のリレーションシップ
  4. 多対多のリレーションシップ
  5. ビューを使った表示
  6. 学部の情報を表示・変更する
  7. キャンパスの情報を表示・変更・削除する
  8. 学生の情報を表示・変更・削除する

Laravel でリレーションシップを使いこなす

多対多のリレーションシップ

概要

ある「学生」が履修できる「講義」は多数あり,ある「講義」を履修する「学生」も多数いることから,「学生」と「講義」の関係は「多対多」になります.

lecture_student

その後のセクションでは,学生の履修登録を変更する方法などを説明します.また,学生の情報を削除したときに連鎖的に履修の情報を削除したり,ある講義の情報を削除したときに学生の履修情報を連鎖的に変更する方法も説明します.

目次に戻る

テーブルの作成

学生と講義の情報を格納するテーブル students と lectures を作成します.なお,テーブル名は先頭小文字の複数形を用いることに注意してください.

vagrant@ubuntu2204 laravelRelationship $ pwd ⏎
/home/vagrant/Documents/laravel/laravelRelationship
vagrant@ubuntu2204 laravelRelationship $ php artisan make:migration create_students_table --create=students ⏎

   INFO  Migration [database/migrations/2023_10_17_162040_create_students_table.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ php artisan make:migration create_lectures_table --create=lectures ⏎

   INFO  Migration [database/migrations/2023_10_17_162102_create_lectures_table.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $

マイグレーションファイルの雛形が生成されたので,students テーブルを生成するためのマイグレーションファイル yyyy_mm_dd_hhmmss_create_students_table を編集します.

database/migrations/2023_10_17_162040_create_students_table.php
    public function up(): void
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id();
            $table->string('name', 100);
            $table->timestamps();
        });
    }

database/migrations/2023_10_17_162102_create_lectures_table.php
    public function up(): void
    {
        Schema::create('lectures', function (Blueprint $table) {
            $table->id();
            $table->string('name', 100);
            $table->timestamps();
        });
    }

マイグレーションファイルの編集が終われば,マイグレーションを実行してデータベースにテーブルを作成します.なお,最初に php artisan migrate status でマイグレーションの実行状況を確認してからマイグレーションを実行すると良いでしょう.今回の場合は campuses と faculties のテーブルがすでに作成ずみであるので,php artisan migrate コマンドでは students と lectures のテーブル作成だけが実行されました.

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name .................................... Batch / Status
  2014_10_12_000000_create_users_table ..................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table ..... [1] Ran
  2019_08_19_000000_create_failed_jobs_table ............... [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table .... [1] Ran
  2023_10_17_131656_create_campuses_table .................. [1] Ran
  2023_10_17_131720_create_faculties_table ................. [1] Ran
  2023_10_17_162040_create_students_table .................. Pending
  2023_10_17_162102_create_lectures_table .................. Pending

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate ⏎

   INFO  Running migrations.

  2023_10_17_162040_create_students_table ................ 13ms DONE
  2023_10_17_162102_create_lectures_table ................. 5ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name .................................... Batch / Status
  2014_10_12_000000_create_users_table ..................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table ..... [1] Ran
  2019_08_19_000000_create_failed_jobs_table ............... [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table .... [1] Ran
  2023_10_17_131656_create_campuses_table .................. [1] Ran
  2023_10_17_131720_create_faculties_table ................. [1] Ran
  2023_10_17_162040_create_students_table .................. [2] Ran
  2023_10_17_162102_create_lectures_table .................. [2] Ran

vagrant@ubuntu2204 laravelRelationship $

目次に戻る

中間テーブルの作成

多対多のリレーションシップを実現するには,2つのテーブルを繋ぐ中間テーブルが必要になります.Laravel では多対多を実現するには,テーブル名を単数にしつつ,アルファベット順に並べ,アンダースコアで区切った名前で中間テーブルを準備しなければならないというルールがあります.つまり,「students」テーブルと「lectures」テーブルでは「lecture_student」という中間テーブル名になります.

このルールに従った「lecture_student」テーブルを生成するためのマイグレーションファイルを作成します.

vagrant@ubuntu2204 laravelRelationship $ pwd ⏎
/home/vagrant/Documents/laravel/laravelRelationship
vagrant@ubuntu2204 laravelRelationship $ php artisan make:migration create_lecture_student_table --create=lecture_student ⏎

   INFO  Migration [database/migrations/2023_10_17_162504_create_lecture_student_table.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $

マイグレーションファイルを編集します.20行目と25行目が外部キーの設定です.どちらのリレーションシップにも onDelete('cascade') によってカスケード削除(連鎖削除)が設定されています.したがって,ある講義の情報を削除するとその操作に伴って中間テーブルからその講義の履修情報が全て連鎖的に削除されます.また,ある学生の退学に伴い情報を削除するとその操作に伴って中間テーブルからその学生の履修情報が全て連鎖的に削除されます

database/migrations/2023_10_17_162504_create_lecture_student_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('lecture_student', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('lecture_id');
            $table->unsignedBigInteger('student_id');
            $table->timestamps();

            $table->foreign('lecture_id')
                  ->references('id')
                  ->on('lectures')
                  ->onDelete('cascade');

            $table->foreign('student_id')
                  ->references('id')
                  ->on('students')
                  ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('lecture_student');
    }
};

マイグレーションファイルの編集ができれば実際にマイグレーションを実行します.今度は中間テーブルの作成だけが実行されました.

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name .................................... Batch / Status
  2014_10_12_000000_create_users_table ..................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table ..... [1] Ran
  2019_08_19_000000_create_failed_jobs_table ............... [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table .... [1] Ran
  2023_10_17_131656_create_campuses_table .................. [1] Ran
  2023_10_17_131720_create_faculties_table ................. [1] Ran
  2023_10_17_162040_create_students_table .................. [2] Ran
  2023_10_17_162102_create_lectures_table .................. [2] Ran
  2023_10_17_162504_create_lecture_student_table ........... Pending

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate ⏎

   INFO  Running migrations.

  2023_10_17_162504_create_lecture_student_table ......... 13ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name .................................... Batch / Status
  2014_10_12_000000_create_users_table ..................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table ..... [1] Ran
  2019_08_19_000000_create_failed_jobs_table ............... [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table .... [1] Ran
  2023_10_17_131656_create_campuses_table .................. [1] Ran
  2023_10_17_131720_create_faculties_table ................. [1] Ran
  2023_10_17_162040_create_students_table .................. [2] Ran
  2023_10_17_162102_create_lectures_table .................. [2] Ran
  2023_10_17_162504_create_lecture_student_table ........... [3] Ran

vagrant@ubuntu2204 laravelRelationship $

目次に戻る

シーダによるデータの投入

3つのテーブルのシーダを生成します.

vagrant@ubuntu2204 laravelRelationship $ php artisan make:seeder StudentsTableSeeder ⏎

   INFO  Seeder [database/seeders/StudentsTableSeeder.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ php artisan make:seeder LecturesTableSeeder ⏎

   INFO  Seeder [database/seeders/LecturesTableSeeder.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ php artisan make:seeder LectureStudentTableSeeder ⏎

   INFO  Seeder [database/seeders/LectureStudentTableSeeder.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $

次に,学生テーブル,講義テーブルと中間テーブルにテスト用のデータを記載します.

database/seeders/StudentsTableSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class StudentsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // 一旦中身を削除する
        DB::table('students')->delete();

        DB::table('students')->insert([
            'name' => '井上'
        ]);

        DB::table('students')->insert([
            'name' => '藤井'
        ]);

        DB::table('students')->insert([
            'name' => '飯田'
        ]);

        DB::table('students')->insert([
            'name' => '足立'
        ]);

        DB::table('students')->insert([
            'name' => '武田'
        ]);
    }
}
database/seeders/LecturesTableSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class LecturesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // 一旦中身を削除する
        DB::table('lectures')->delete();

        DB::table('lectures')->insert([
            'name' => '経営戦略論'
        ]);

        DB::table('lectures')->insert([
            'name' => '管理会計'
        ]);

        DB::table('lectures')->insert([
            'name' => '情報ネットワーク論'
        ]);
    }
}
database/seeders/LectureStudentTableSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class LectureStudentTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // 一旦中身を削除する
        DB::table('lecture_student')->delete();

        DB::table('lecture_student')->insert([
            'lecture_id' => 1,
            'student_id' => 1
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 2,
            'student_id' => 1
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 1,
            'student_id' => 2
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 3,
            'student_id' => 2
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 1,
            'student_id' => 3
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 2,
            'student_id' => 3
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 3,
            'student_id' => 3
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 2,
            'student_id' => 4
        ]);

        DB::table('lecture_student')->insert([
            'lecture_id' => 3,
            'student_id' => 4
        ]);
    }
}

さらに DatabaseSeeder.php には今追加した3つのシーダを実行するコードを追加します.

database/seeders/DatabaseSeeder.php
<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        $this->call(CampusesTableSeeder::class);
        $this->call(FacultiesTableSeeder::class);
        $this->call(StudentsTableSeeder::class);
        $this->call(LecturesTableSeeder::class);
        $this->call(LectureStudentTableSeeder::class);
    }
}

シーダの準備ができたので,シーダを実行してテーブルにデータを投入します.このとき,php artisan db:seed を実行すると,DatabaseSeeder.php に記載されたシーダが全て順番に実行されます.つまり,campuses や faculties はすでに投入済みであることから,これらが再び実行されてしまうことになる.これにより,1 番からスタートするはずの ID がずれてしまうなどの問題が発生する.このような場合は,まだ実行されていないシーダだけを実行するか,データベースを一旦すべてリセットしてからマイグレーション,シーダの順番に実行する方法がある.(ただし,本番環境でロールバックを実施しないように注意してください!)

まず,campuses や faculties にはデータがすでに格納されているので,新たな 3 つのシーダを順番に実行します.

vagrant@ubuntu2204 laravelRelationship $ php artisan db:seed --class=StudentsTableSeeder ⏎

   INFO  Seeding database.

vagrant@ubuntu2204 laravelRelationship $ php artisan db:seed --class=LecturesTableSeeder ⏎

   INFO  Seeding database.

vagrant@ubuntu2204 laravelRelationship $ php artisan db:seed --class=LectureStudentTableSeeder ⏎

   INFO  Seeding database.

vagrant@ubuntu2204 laravelRelationship $

次は,データベースをロールバックしてから再度投入すること考えます.php artisan migrate:rollback でデータベースのロールバックが可能です.しかし一度のロールバックでは直前のマイグレーションで生成されたテーブルだけがロールバックされます.したがって,マイグレーションの状況を確認しながら,ロールバックを何度か繰り返して全てのテーブルがリセットされたのを確認してからマイグレーションして,シーダを実行します.最後にはロールバック,マイグレーション,シーダの3つのコマンドを連続して実行しています.

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name ................................... Batch / Status
  2014_10_12_000000_create_users_table .................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table .... [1] Ran
  2019_08_19_000000_create_failed_jobs_table .............. [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table ... [1] Ran
  2023_10_17_131656_create_campuses_table ................. [1] Ran
  2023_10_17_131720_create_faculties_table ................ [1] Ran
  2023_10_17_162040_create_students_table ................. [2] Ran
  2023_10_17_162102_create_lectures_table ................. [2] Ran
  2023_10_17_162504_create_lecture_student_table .......... [3] Ran

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:rollback ⏎

   INFO  Rolling back migrations.

  2023_10_17_162504_create_lecture_student_table ........ 10ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name ................................... Batch / Status
  2014_10_12_000000_create_users_table .................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table .... [1] Ran
  2019_08_19_000000_create_failed_jobs_table .............. [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table ... [1] Ran
  2023_10_17_131656_create_campuses_table ................. [1] Ran
  2023_10_17_131720_create_faculties_table ................ [1] Ran
  2023_10_17_162040_create_students_table ................. [2] Ran
  2023_10_17_162102_create_lectures_table ................. [2] Ran
  2023_10_17_162504_create_lecture_student_table .......... Pending

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:rollback ⏎

   INFO  Rolling back migrations.

  2023_10_17_162102_create_lectures_table ............... 12ms DONE
  2023_10_17_162040_create_students_table ................ 5ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name ................................... Batch / Status
  2014_10_12_000000_create_users_table .................... [1] Ran
  2014_10_12_100000_create_password_reset_tokens_table .... [1] Ran
  2019_08_19_000000_create_failed_jobs_table .............. [1] Ran
  2019_12_14_000001_create_personal_access_tokens_table ... [1] Ran
  2023_10_17_131656_create_campuses_table ................. [1] Ran
  2023_10_17_131720_create_faculties_table ................ [1] Ran
  2023_10_17_162040_create_students_table ................. Pending
  2023_10_17_162102_create_lectures_table ................. Pending
  2023_10_17_162504_create_lecture_student_table .......... Pending

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:rollback ⏎

   INFO  Rolling back migrations.

  2023_10_17_131720_create_faculties_table .............. 11ms DONE
  2023_10_17_131656_create_campuses_table ................ 4ms DONE
  2019_12_14_000001_create_personal_access_tokens_table .. 5ms DONE
  2019_08_19_000000_create_failed_jobs_table ............. 4ms DONE
  2014_10_12_100000_create_password_reset_tokens_table ... 5ms DONE
  2014_10_12_000000_create_users_table ................... 4ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:status ⏎

  Migration name ................................... Batch / Status
  2014_10_12_000000_create_users_table .................... Pending
  2014_10_12_100000_create_password_reset_tokens_table .... Pending
  2019_08_19_000000_create_failed_jobs_table .............. Pending
  2019_12_14_000001_create_personal_access_tokens_table ... Pending
  2023_10_17_131656_create_campuses_table ................. Pending
  2023_10_17_131720_create_faculties_table ................ Pending
  2023_10_17_162040_create_students_table ................. Pending
  2023_10_17_162102_create_lectures_table ................. Pending
  2023_10_17_162504_create_lecture_student_table .......... Pending

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate ⏎

   INFO  Running migrations.

  2014_10_12_000000_create_users_table .................. 11ms DONE
  2014_10_12_100000_create_password_reset_tokens_table ... 4ms DONE
  2019_08_19_000000_create_failed_jobs_table ............. 8ms DONE
  2019_12_14_000001_create_personal_access_tokens_table . 11ms DONE
  2023_10_17_131656_create_campuses_table ................ 4ms DONE
  2023_10_17_131720_create_faculties_table ............... 4ms DONE
  2023_10_17_162040_create_students_table ................ 4ms DONE
  2023_10_17_162102_create_lectures_table ................ 4ms DONE
  2023_10_17_162504_create_lecture_student_table ......... 4ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan db:seed ⏎

   INFO  Seeding database.

  Database\Seeders\CampusesTableSeeder .................... RUNNING
  Database\Seeders\CampusesTableSeeder .............. 24.39 ms DONE

  Database\Seeders\FacultiesTableSeeder ................... RUNNING
  Database\Seeders\FacultiesTableSeeder ............. 40.01 ms DONE

  Database\Seeders\StudentsTableSeeder .................... RUNNING
  Database\Seeders\StudentsTableSeeder .............. 21.49 ms DONE

  Database\Seeders\LecturesTableSeeder .................... RUNNING
  Database\Seeders\LecturesTableSeeder .............. 12.29 ms DONE

  Database\Seeders\LectureStudentTableSeeder .............. RUNNING
  Database\Seeders\LectureStudentTableSeeder ........ 39.04 ms DONE

vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:rollback; php artisan migrate; php artisan db:seed; ⏎

   INFO  Rolling back migrations.

  2023_10_17_162504_create_lecture_student_table ........ 16ms DONE
  2023_10_17_162102_create_lectures_table ................ 6ms DONE
  2023_10_17_162040_create_students_table ................ 5ms DONE
  2023_10_17_131720_create_faculties_table ............... 5ms DONE
  2023_10_17_131656_create_campuses_table ................ 5ms DONE
  2019_12_14_000001_create_personal_access_tokens_table .. 6ms DONE
  2019_08_19_000000_create_failed_jobs_table ............. 5ms DONE
  2014_10_12_100000_create_password_reset_tokens_table ... 5ms DONE
  2014_10_12_000000_create_users_table ................... 5ms DONE


   INFO  Running migrations.

  2014_10_12_000000_create_users_table .................. 11ms DONE
  2014_10_12_100000_create_password_reset_tokens_table ... 4ms DONE
  2019_08_19_000000_create_failed_jobs_table ............. 8ms DONE
  2019_12_14_000001_create_personal_access_tokens_table . 12ms DONE
  2023_10_17_131656_create_campuses_table ................ 4ms DONE
  2023_10_17_131720_create_faculties_table ............... 5ms DONE
  2023_10_17_162040_create_students_table ................ 4ms DONE
  2023_10_17_162102_create_lectures_table ................ 4ms DONE
  2023_10_17_162504_create_lecture_student_table ......... 4ms DONE


   INFO  Seeding database.

  Database\Seeders\CampusesTableSeeder .................... RUNNING
  Database\Seeders\CampusesTableSeeder .............. 15.63 ms DONE

  Database\Seeders\FacultiesTableSeeder ................... RUNNING
  Database\Seeders\FacultiesTableSeeder ............. 71.50 ms DONE

  Database\Seeders\StudentsTableSeeder .................... RUNNING
  Database\Seeders\StudentsTableSeeder .............. 21.29 ms DONE

  Database\Seeders\LecturesTableSeeder .................... RUNNING
  Database\Seeders\LecturesTableSeeder .............. 12.77 ms DONE

  Database\Seeders\LectureStudentTableSeeder .............. RUNNING
  Database\Seeders\LectureStudentTableSeeder ........ 39.29 ms DONE

vagrant@ubuntu2204 laravelRelationship $

目次に戻る

SQLite で確認する

シーダでデータの投入ができたので,sqlite3 で確認してみます.結合 (INNER JOIN) によってどの学生がどの講義を履修しているのかが確認できました.

vagrant@ubuntu2204 laravelRelationship $ pwd ⏎
/home/vagrant/Documents/laravel/laravelRelationship
vagrant@ubuntu2204 laravelRelationship $ ls ⏎
README.md  bootstrap      config        phpunit.xml  routes   vendor
app        composer.json  database      public       storage  vite.config.js
artisan    composer.lock  package.json  resources    tests
vagrant@ubuntu2204 laravelRelationship $ cd database/ ⏎
vagrant@ubuntu2204 database $ ls ⏎
database.sqlite  factories  migrations  seeders
vagrant@ubuntu2204 database $ sqlite3 database.sqlite ⏎
SQLite version 3.38.2 2022-03-26 13:51:10
Enter ".help" for usage hints.
sqlite> .tables ⏎
campuses                lectures                students
faculties               migrations              users
failed_jobs             password_reset_tokens
lecture_student         personal_access_tokens
sqlite> .headers ON ⏎
sqlite> SELECT * FROM students; ⏎
id|name|created_at|updated_at
1|井上||
2|藤井||
3|飯田||
4|足立||
5|武田||
sqlite> SELECT * FROM lectures; ⏎
id|name|created_at|updated_at
1|経営戦略論||
2|管理会計||
3|情報ネットワーク論||
sqlite> SELECT * FROM lecture_student; ⏎
id|lecture_id|student_id|created_at|updated_at
1|1|1||
2|2|1||
3|1|2||
4|3|2||
5|1|3||
6|2|3||
7|3|3||
8|2|4||
9|3|4||
sqlite> SELECT students.id, students.name, lectures.name
   ...> FROM students
   ...> INNER JOIN lecture_student ON
   ...> students.id = lecture_student.student_id
   ...> INNER JOIN lectures ON
   ...> lectures.id = lecture_student.lecture_id
   ...> ORDER BY students.id; ⏎
id|name|name
1|井上|経営戦略論
1|井上|管理会計
2|藤井|経営戦略論
2|藤井|情報ネットワーク論
3|飯田|経営戦略論
3|飯田|管理会計
3|飯田|情報ネットワーク論
4|足立|管理会計
4|足立|情報ネットワーク論
sqlite> .exit ⏎
vagrant@ubuntu2204 database $ cd .. ⏎
vagrant@ubuntu2204 laravelRelationship $

目次に戻る

モデルの作成

Student モデルと Lecture モデルを作成します.繰り返しになりますが,モデル名は先頭大文字の単数形で命名します.

vagrant@ubuntu2204 laravelRelationship $ pwd ⏎
/home/vagrant/Documents/laravel/laravelRelationship
vagrant@ubuntu2204 laravelRelationship $ ls app/Models/ ⏎
Campus.php  Faculty.php  User.php
vagrant@ubuntu2204 laravelRelationship $ php artisan make:model Student ⏎

   INFO  Model [app/Models/Student.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ php artisan make:model Lecture ⏎

   INFO  Model [app/Models/Lecture.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ ls app/Models/ ⏎
Campus.php  Faculty.php  Lecture.php  Student.php  User.php
vagrant@ubuntu2204 laravelRelationship $

目次に戻る

コントローラの作成

Student モデルと Lecture モデルに関連するコントローラを作成します.ここでもやはりコントローラ名は先頭大文字の複数形(または単数形)で命名することに注意していください.

vagrant@ubuntu2204 laravelRelationship $ ls app/Http/Controllers/ ⏎
CampusesController.php  Controller.php  FacultiesController.php
vagrant@ubuntu2204 laravelRelationship $ php artisan make:controller StudentsController ⏎

   INFO  Controller [app/Http/Controllers/StudentsController.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ php artisan make:controller LecturesController ⏎

   INFO  Controller [app/Http/Controllers/LecturesController.php] created successfully.

vagrant@ubuntu2204 laravelRelationship $ ls app/Http/Controllers/ ⏎
CampusesController.php  FacultiesController.php  StudentsController.php
Controller.php          LecturesController.php
vagrant@ubuntu2204 laravelRelationship $

目次に戻る

ルートの定義と一覧表示の雛形

まず,現時点でのルートの定義を確認します.

vagrant@ubuntu2204 laravelRelationship $ php artisan route:list ⏎

  GET|HEAD   / .......................................................................
  POST       _ignition/execute-solution ignition.executeSolution › Spatie\LaravelIgni…
  GET|HEAD   _ignition/health-check ignition.healthCheck › Spatie\LaravelIgnition › H…
  POST       _ignition/update-config ignition.updateConfig › Spatie\LaravelIgnition  …
  GET|HEAD   api/user ................................................................
  GET|HEAD   campuses ...................... campuses.index › CampusesController@index
  GET|HEAD   faculties ................... faculties.index › FacultiesController@index
  GET|HEAD   sanctum/csrf-cookie sanctum.csrf-cookie › Laravel\Sanctum › CsrfCookieCo…

                                                                    Showing [8] routes

vagrant@ubuntu2204 laravelRelationship $

/students と /lectures の URI が指定されたときに,それぞれのコントローラの index 関数が呼び出されるように routes/web にルートを定義します.

routes/web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CampusesController;
use App\Http\Controllers\FacultiesController;
use App\Http\Controllers\StudentsController;
use App\Http\Controllers\LecturesController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/campuses', [CampusesController::class, 'index']) -> name('campuses.index');
Route::get('/faculties', [FacultiesController::class, 'index']) -> name('faculties.index');
Route::get('/students', [StudentsController::class, 'index']) -> name('students.index');
Route::get('/lectures', [LecturesController::class, 'index']) -> name('lectures.index');

再びルートを確認します.

vagrant@ubuntu2204 laravelRelationship $ php artisan route:list ⏎

  GET|HEAD   / .......................................................................
  POST       _ignition/execute-solution ignition.executeSolution › Spatie\LaravelIgni…
  GET|HEAD   _ignition/health-check ignition.healthCheck › Spatie\LaravelIgnition › H…
  POST       _ignition/update-config ignition.updateConfig › Spatie\LaravelIgnition  …
  GET|HEAD   api/user ................................................................
  GET|HEAD   campuses ...................... campuses.index › CampusesController@index
  GET|HEAD   faculties ................... faculties.index › FacultiesController@index
  GET|HEAD   lectures ...................... lectures.index › LecturesController@index
  GET|HEAD   sanctum/csrf-cookie sanctum.csrf-cookie › Laravel\Sanctum › CsrfCookieCo…
  GET|HEAD   students ...................... students.index › StudentsController@index

                                                                   Showing [10] routes

vagrant@ubuntu2204 laravelRelationship $

app/Http/Controllers/ 以下の StudentsController.php と LecturesController.php に一覧表示の雛形を作成します.

app/HTTP/Controllers/StudentsController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class StudentsController extends Controller
{
    public function index()
    {
        dd('List of Students');
    }
}
app/HTTP/Controllers/LecturesController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class LecturesController extends Controller
{
    public function index()
    {
        dd('List of Students');
    }
}

Web サーバを起動して,実際に /students と /lectures にアクセスします.

vagrant@ubuntu2204 laravelRelationship $ php artisan serve --host=192.168.56.101 --port=8000

   INFO  Server running on [http://192.168.56.101:8000].

  Press Ctrl+C to stop the server
laravel10-2023-relationship-07.png
laravel10-2023-relationship-08.png

目次に戻る

リレーションシップを設定する

ようやくリレーションシップを設定する準備ができました.ある学生が履修することのできる講義は複数あり,ある講義は複数の学生が履修することができるので,「学生と講義の関係は多対多」になります.一対多の場合と似ていますが,「学生 (Student)」クラスでは,その学生が履修している講義のリストを取得する lectures メソッドを定義します.同様に「講義 (Lecture)」クラスでも,その講義を履修している学生のリストを取得するための students メソッドを定義します.次のようにそれぞれのモデルに belongsToMany() を使ってリレーションシップを指定します.

app/Models/Student.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
    use HasFactory;

    // Many to Many
    public function lectures()
    {
        return $this->belongsToMany('App\Models\Lecture');
    }
}
app/Models/Lecture.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Lecture extends Model
{
    use HasFactory;

    // Many to Many
    public function students()
    {
        return $this->belongsToMany('App\Models\Student');
    }
}

モデルにリレーションシップのメソッドを記載できたら,次はコントローラから呼び出してみます.

app/HTTP/Controllers/StudentsController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Student;

class StudentsController extends Controller
{
    public function index()
    {
        $students = Student::get();
        foreach ($students as $student) {
            dump("+++++++++++++++");
            dump($student->name);
            foreach($student->lectures as $lecture) {
                dump($lecture->name);
            }
        }
    }
}

app/HTTP/Controllers/LecturesController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Lecture;

class LecturesController extends Controller
{
    public function index()
    {
        $lectures = Lecture::get();
        foreach ($lectures as $lecture) {
            dump("+++++++++++++++");
            dump($lecture->name);
            foreach($lecture->students as $student) {
                dump($student->name);
            }
        }
    }
}

Web サーバを起動して,実際に /students と /lectures にアクセスします.

vagrant@ubuntu2204 laravelRelationship $ php artisan serve --host=192.168.56.101 --port=8000

   INFO  Server running on [http://192.168.56.101:8000].

  Press Ctrl+C to stop the server
laravel10-2023-relationship-09.png
laravel10-2023-relationship-10.png

目次に戻る