Laravel入門5 Todoアプリ(データベース)
記事一覧
- Laravel × Docker 最速環境構築
 - Laravel 入門1 ページ追加
 - Laravel入門2 bladeディレクティブ
 - Laravel入門3 静的ファイル
 - Laravel入門4 Request
 - Laravel入門5 Todoアプリ(データベース)
 - Laravel入門6 Todoアプリ(認証機能)
 - Laravel入門7 Todoアプリ(CRUD)
 
データベースとテーブル
データベースとは
データを保存しておく場所で、必要なときにデータを取り出したり、更新したりできるもの
テーブルとは
エクセルのシートのようなもので、データベース1つに対して複数含まれる

環境設定
- ファイルを編集
 
- Dockerfile
 
FROM php:8.4
WORKDIR /workdir
COPY  /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER=1
ENV COMPOSER_HOME="/opt/composer"
ENV PATH="$PATH:/opt/composer/vendor/bin"
RUN apt-get update
RUN apt-get install -y zip
RUN docker-php-ext-install pdo_mysql
COPY . .
WORKDIR /workdir/laravel_app
RUN composer install
CMD ["php", "artisan", "serve", "--host", "0.0.0.0"]
EXPOSE 8000
- docker-compose.yml
 
services:
  app:
    build: ./
    volumes:
      - .:/workdir
    ports:
      - 8000:8000
  db:
    image: mysql:8.3
    volumes:
      - ./laravel_app/mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: dev
    ports:
      - 3306:3306
- 
laravel_app/.env
データベースの接続設定を編集 
- DB_CONNECTION=sqlite
- DB_HOST=127.0.0.1
- DB_PORT=3306
- DB_DATABASE=laravel
- DB_USERNAME=root
- DB_PASSWORD=
+ DB_CONNECTION=mysql # mysqlに変更
+ DB_HOST=db # サービス名に変更
+ DB_PORT=3306
+ DB_DATABASE=dev # 接続するデータベース
+ DB_USERNAME=root
+ DB_PASSWORD=password # パスワード
- ターミナル(コンテナ外)でコマンドを実行
 
docker compose build
docker compose up -d
以下のようになればOK
.
├── laravel_app/
│   └── mysql_data
├── docker-compose.yml
└── Dockerfile
- ターミナル(コンテナ内)でコマンド実行
 
- コンテナに入る
 
docker compose run app bash
- コンテナ内で実行
 
# データベースの更新(後でやります。)
php artisan migrate
以下のように出ればOK
   INFO  Preparing database.  
  Creating migration table ............................................... 12.19ms DONE
   INFO  Running migrations.  
  0001_01_01_000000_create_users_table ................................... 29.03ms DONE
  0001_01_01_000001_create_cache_table .................................... 8.75ms DONE
  0001_01_01_000002_create_jobs_table .................................... 23.83ms DONE
モデルとマイグレーションファイル
アプリケーションでデータベースを用いる際には、以下のようなものを使います。
- モデル
 - マイグレーションファイル
 
モデルとは
プログラムを用いて、テーブルのデータを取得・登録・更新・削除するためのもの
(1つのテーブルに対して、1つのモデルを作成する)
マイグレーションファイルとは
プログラムを用いてテーブルの自体の作成, 編集, 削除などを行うためのファイル
ファイルの場所
.
├── laravel_app
│   ├── app
│   │   └── Models # モデルファイル
│   └── database
│       └── migrations # マイグレーションファイル
├── docker-compose.yml
└── Dockerfile
ファイルの作成
- コンテナに入る
 
docker compose run app bash
- ターミナル(コンテナ内)で以下コマンドを実行
 
モデルファイルを作るコマンドを実行
(-m を使用することで対応するマイグレーションファイルも同時に作成可能)
(今回はtasksテーブルを作成するので、Taskモデルにします)
# php artisan make:model モデル名
php artisan make:model Task -m
以下のようにファイルが作成されればOK
.
├── laravel_app
│   ├── app
│   │   └── Models
│   │       └── Task.php # tasksテーブル用のモデル
│   └── database
│       └── migrations
│           └── xxxx_xx_xx_xxxxxx_create_tasks_table.php # tasksテーブル用のマイグレーションファイル
├── docker-compose.yml
└── Dockerfile
マイグレーションファイルの編集
- xxxx_xx_xx_xxxxxx_create_tasks_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('tasks', function (Blueprint $table) {
            $table->id();
            // $table->テーブルの型('カラム名');
            $table->unsignedBigInteger('user_id'); # user_idカラムを追加
            $table->string('title'); # titleカラムを追加
            $table->text('content'); # contentカラムを追加
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('tasks');
    }
};
モデルの編集
- Task.php
 
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
    // カラムを配列で指定する
    protected $fillable = ['user_id', 'title', 'content'];
}
マイグレート
マイグレートとは
データベースに対してマイグレーションファイルに記述した変更を適用すること
(php artisan migrateでできる)
実行
- コンテナに入る
 
docker compose run app bash
- ターミナル(コンテナ内)で以下コマンドを実行
 
php artisan migrateはマイグレーションファイルの変更を適用するコマンド
php artisan migrate
以下のようなテーブルができます(データは例)
- tasksテーブル
 
| id | user_id | title | content | created_at | updated_at | 
|---|---|---|---|---|---|
| 1 | 1 | 買い物リスト作成 | 週末のための買い物リストを作る | 2025-04-20 10:00:00 | 2025-04-20 10:00:00 | 
| 2 | 1 | レポート提出 | 月曜日までにレポートを提出する | 2025-04-20 11:30:00 | 2025-04-20 11:45:00 | 
| 3 | 2 | 読書 | 「Laravel入門」を読む | 2025-04-20 12:00:00 | 2025-04-20 12:15:00 | 
モデルの使い方(座学)
モデルをインポートする
# use App\Models\モデル名;
use App\Models\Task;
モデルを使用する
// 以下のようにする
// モデル::処理1()->処理2()->処理3()...;
// tasksテーブルからuser_idが1のものを取得できる。
$task = Task::where('user_id', 1)->get();
// where()は絞り込み
// get()は取得
リレーション(座学)
リレーションとは
テーブル同士のつながりのこと
1対1
1つのUserに対して1つのProfileが結びついている場合
(usersテーブルのid = profilesテーブルuser_id)
例: ケイトのプロフィールにはエンジニア。猫好き。と書かれている
- users
 
| id | name | |
|---|---|---|
| 1 | ケイト | keito@example.com | 
| 2 | ユカ | yuka@example.com | 
- profiles
 
| id | user_id | bio | birthday | 
|---|---|---|---|
| 1 | 1 | エンジニア。猫好き。 | 2000-04-21 | 
| 2 | 2 | デザイナー。旅行好き。 | 1999-11-05 | 
- Userモデル内に以下のように記述する
 
class User extends Model
{
  function profile() {
      return $this->hasOne(Profile::class);
  }
}
- コントローラーでの使用例
 
// 1. find(1)でidが1のUserを絞り込み
// 2. そのユーザーに紐付いているProfileのみを取得
$profile = User::find(1)->profile;
1対多
1つのUserに対して複数ののTaskが結びついている場合
(usersテーブルのid = tasksテーブルuser_id)
例: ケイトはレポート作成とミーティング準備の二つのタスクを持っている
- users
 
| id | name | |
|---|---|---|
| 1 | ケイト | keito@example.com | 
| 2 | ユカ | yuka@example.com | 
- tasks
 
| id | user_id | title | status | 
|---|---|---|---|
| 1 | 1 | レポート作成 | 未完了 | 
| 2 | 1 | ミーティング準備 | 完了 | 
| 3 | 2 | デザイン修正 | 未完了 | 
- Userモデル内に以下のように記述する
 
class User extends Model
{
  // リレーション先が複数ある場合は複数形の方が良い
  function tasks() {
      return $this->hasMany(Task::class);
  }
}
- コントローラーでの使用例
 
// 1. find(1)でidが1のUserを絞り込み
// 2. そのユーザーに紐付いているTaskのみを取得
$tasks = User::find(1)->tasks;
多対1
複数のUserに対して1つのCompanyが結びついている場合
(usersテーブルのcompany_id = companiesテーブルのid)
例: ケイトとユカはテック株式会社に所属している
- users
 
| id | name | company_id | |
|---|---|---|---|
| 1 | ケイト | keito@example.com | 1 | 
| 2 | ユカ | yuka@example.com | 1 | 
- companies
 
| id | name | 
|---|---|
| 1 | テック株式会社 | 
| 2 | グリーン株式会社 | 
- Userモデル内に以下のように記述する
 
class User extends Model
{
  function company() {
      return $this->belongsTo(Company::class);
  }
}
- コントローラーでの使用例
 
// 1. find(1)でidが1のUserを絞り込み
// 2. そのユーザーに紐付いているCompanyのみを取得
$company = User::find(1)->company;
多対多
複数のUserに対して複数ののGroupが結びついている場合
(usersテーブルのid = group_usersテーブルのuser_id)
(groupsテーブルのid = group_usersテーブルのgroup_id)
例: ケイトは開発者グループとデザイナーグループどちらにも入っている
【重要】多対多の場合は中間テーブルを使います。
(中間テーブルの命名は、紐付くテーブルをアンダーバー区切りでアルファベット順に並べたものが良い。)
- users
 
| id | name | |
|---|---|---|
| 1 | ケイト | keito@example.com | 
| 2 | ユカ | yuka@example.com | 
- group_users
 
| group_id | user_id | 
|---|---|
| 1 | 1 | 
| 1 | 2 | 
| 2 | 1 | 
- groups
 
| id | name | 
|---|---|
| 1 | 開発者 | 
| 2 | デザイナー | 
- Userモデル内に以下のように記述する
 
class User extends Model
{
  function groups() {
      return $this->belongsToMany(Group::class);
  }
}
- コントローラーでの使用例
 
// 1. find(1)でidが1のUserを絞り込み
// 2. そのユーザーに紐付いているGroupのみを取得
$groups = User::find(1)->groups;
Discussion