改訂版!!Laravel8でTwitterクローンを作る【Step01 : DB設計とMigration】

11 min read読了の目安(約6900字

はじめに

どーも 弁護士ドットコム でエンジニアしていますナミザトです👨‍🚀

以前QiitaでLaravel5.8で作成した記事が好評だったのでそのリニューアルLaravel8.x版です!
せっかくなのでLaravel8から実装されたJetstream🚀や変更された実装方法なども試してみたいと思います!

2020.09 現在時点

概要

最近では色々教材も増えてきて、Laravel5.8で執筆していた頃よりも需要は少ないと思いますが、
スクール形式(知ってる前提もあるけどなるべく機能の一つ一つを説明)でやりたい方や、
Laravel8.xを試してみたいけど情報がなさすぎて詰まった時が怖いなどの方達の助けになれればと思い執筆します!

あとめちゃくちゃ書き直してるのでLaravel5.8やったよ!って人もぜひ><

早速記念すべき第1回はDB設計とMigration(マイグレーション)を学んでいきます

前提

  • PHP&DB知識がある程度ある
  • MVC構造をある程度理解している
  • 環境構築済み(DB接続含め)

Laravel初心者を脱却したい!という方はこちらも合わせてどうぞ!
Laravelワカンネ(゚⊿゚)から「完全に理解した()」までステップアップ

環境

  • Mac
  • Docker
  • Laravel8.x

今回はDockerを使用していますが、Vagrant/MAMP/ローカル何でもOKです!

要件定義

まずはTwitterチュートリアルと言えど、Twitterをそのまま作るのは不可能()なので、
今回最低限必要な機能をざっと洗い出してみましょう!

  • ユーザーは新規登録&ログインができる
  • ログイン状態でなければ記事の閲覧&投稿はできない
  • ユーザーは記事を投稿できる(ツイート)
  • ツイートに対してコメントといいねができる
  • コメントにはいいねとコメントはできない(めんどくさい)
  • ユーザー同士はフォロー&フォロー解除ができる
  • 自身のタイムラインにはフォローしているユーザーのツイートのみ閲覧できる

DB設計

では上記の要件定義で洗い出した機能から必要になりそうなテーブルを洗い出してみましょう
ざっとこんな感じでしょうか。

  • usersテーブル
    • ユーザーを管理するテーブル
  • tweetsテーブル
    • ユーザー毎のツイートを管理するテーブル
  • commentsテーブル
    • ツイートに対したコメントを管理するテーブル
  • favoritesテーブル
    • ツイートに対したいいねを管理するテーブル
  • followersテーブル
    • フォロー関係を管理するテーブル

文字だけじゃ分かりづらいと思うので、画像にしてみましょう

0と1の区別してないのは許してください

何となく一対多の関係を想像できたと思いますので(無理やり)
早速次の章で上記のテーブルを作成していきましょう!

Migration(マイグレーション)

Migrationとは言うならばテーブルの設計図/記録書のようなものです
Laravelではざっくり3つのメリットがあります

  1. SQLを書かずにLaravelの仕様に沿った書き方でテーブルを作成/削除などができる
  2. テーブルの作成/更新/削除などをファイルで日付順で管理するため現状把握しやすい
  3. ファイル形式なのでわざわざSQLファイルをimportせずとも簡単に共有でき、実行も簡単

Laravelに限らず最近のwebフレームワークではほとんどMigration機能を実装しています

artisanコマンド

Laravelにはartisanコマンドというターミナルで使用できる便利なコマンドが用意されています
例えば以下のコマンドを入力するとapp/Http/Controllersの中にSampleContorller.phpというファイルが最初からクラスやnamespaceを定義した状態で生成されます

php artisan make:controller SampleController

上記の要領でMigrationとModelを作っていきたいと思います!

Migrationファイルの作成

テーブルを作成するときは下記のようなコマンドを入力します

php artisan make:migration create_example_table

Laravelでは大抵の場合テーブル1つに付き1つのモデルを用意することが多いので、(中間テーブル等は除く)
今回はartisanコマンドに用意されているMigrationとModelを同時に作成するコマンドで試していきたいと思います

以下は全てターミナルでLaravelのプロジェクト内で実行します

tweetsテーブル

php artisan make:model Tweet -m

commentsテーブル

php artisan make:model Comment -m

followersテーブル

php artisan make:model Follower -m

favoritesテーブル

php artisan make:migration create_fovorites_table

こちらは中間テーブルとして使用するのでモデルは不要

Migrationの書き方

ユーザー関連のみ最初からMigrationが用意されているのでそれを元に説明していきます

2014_10_12_000000_create_users_table.php

<?php

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

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

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

今回はテーブルを作成するのでup()メソッドに作成するテーブルと作成するカラムを定義しています
逆にdown()メソッドにはrollbackする際の定義を書きます(テーブルを削除する)

カラムの書き方はSQLでINSERT TABLEしたことある人なら何となく分かると思うので省略します
詳しく知りたい方は こちら から

Migrationの使い方が何となく伝わったと思うので、実際にusersテーブルに対して変更を加えていきます

usersテーブル

以下からコードを省略してup()メソッドだけ記述します

2014_10_12_000000_create_users_table.php

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('screen_name')->unique()->comment('アカウント名');
        $table->string('name')->comment('ユーザー名');
        $table->string('profile_image')->nullable()->comment('プロフィール画像');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

tweetsテーブル

2020_09_25_060211_create_tweets_table.php

public function up()
{
    Schema::create('tweets', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->comment('ユーザID');
        $table->string('text')->comment('ツイート本文');
        $table->softDeletes();
        $table->timestamps();

        $table->index('user_id');
    });
}

commentsテーブル

2020_09_25_060252_create_comments_table.php

public function up()
{
    Schema::create('comments', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->comment('ユーザID');
        $table->foreignId('tweet_id')->constrained()->comment('ツイートID');
        $table->string('text')->comment('コメント本文');
        $table->softDeletes();
        $table->timestamps();

        $table->index(['user_id', 'tweet_id']);
    });
}

favoritesテーブル

2020_09_25_060332_create_favorites_table.php

public function up()
{
    Schema::create('fovorites', function (Blueprint $table) {
        $table->foreignId('user_id')->constrained()->comment('ユーザID');
        $table->foreignId('tweet_id')->constrained()->comment('ツイートID');

        $table->unique(['user_id', 'tweet_id']);
    });
}

favoriteテーブルを中間テーブルとして使用する為、カラムはuser_idtweet_idのみとしてます

この部分では複合インデックスを作成しています

$table->unique(['user_id', 'tweet_id']);

followersテーブル

自分自身はfollowing_idになり、フォローしているユーザーはfollowed_id

2020_09_25_060412_create_followers_table.php

public function up()
{
    Schema::create('followers', function (Blueprint $table) {
        $table->foreignId('following_id')->constrained('users')->comment('フォローしているユーザーのID');
        $table->foreignId('followed_id')->constrained('users')->comment('フォローされているユーザーのID');

        $table->unique(['following_id', 'followed_id']);
    });
}

ここまでさらりと書きましたが、実はMigrationの書き方もLaravel7.xから新しい記述方法が推奨されており、今回はその推奨方法に従って記述しています

詳しくは こちらの記事 から

Migrationは日付順で上から実行されるため外部キー制約を定義している場合は順番に気をつけましょう

Migrationを実行

以下のコマンドで先ほど作成したMigrationファイルを実行してDBにテーブルを作成します!

php artisan migrate

Migration table created successfully.と表示されたら成功です
第1回はとりあえずここまで!


最後に

弁護士ドットコムでは一緒に働く仲間を募集しています
求人情報は こちら から!!