【Laravel実務に使える】マイグレーションの作成から一覧画面表示まで

暇なときに予定を探せるアプリ[yoteiPicker](https://yoteipicker.com/)をリリースしました。


Laravelでマイグレーション作成から一覧画面の表示まで解説します。

動作環境
Docker 20.10.7
PHP 7.4.22
Laravel 8.53.1
mySQL 5.7
データベースのツール　phpmyadmin
mac

dockerとlaravelで仮想環境を作成していますが、基本的にMAMP環境でもhomesteadでも同様に動くと思います。

[＞＞フリーランスも対象！エンジニア転職におすすめなサイト5選](https://www.kamome-susume.com/enginner-job-change-site/
)

#この記事のゴール
本を管理するアプリを想定しています。

テーブルは以下のように設計
usersテーブル

| user_id | user_name | email | password |
|:-----------|------------:|:------------:|:------------:|
| 主キー       | ユーザー名        | メールアドレス        |パスワード       |
| id       | string        | string        |string       |

booksテーブル

| book_id | user_id | category_id | book_name |
|:-----------|------------:|:------------:|:------------:|
| 主キー       | ユーザー外部キー        | カテゴリー        |本の名前         |
| id      | bigInteger      | bigInteger        |string        |


categoriesテーブル

| category_id | user_id | category_name | 
|:-----------|------------:|:------------:|:------------:|
| 主キー       | ユーザー外部キー        | カテゴリー名        |
| id       | bigInteger        | string       |

【流れ】
テーブルが設計できたら、マイグレーションファイルを作成して、実行。
モデル、コントローラー作成して、ルーティングを記述。
ビューを作成して、一覧画面を表示させる。

この記事では上記の流れを解説します。

#マイグレーションの作成

今回は、booksテーブルとcategoriesテーブルを作成します。
※usersテーブルに関しては、マイグレーションファイルが元から作成されているはずなので、そのマイグレーションファイルを編集してください。

usersのマイグレーションファイル

```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('user_id');
            $table->string('user_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');
    }
}

```

`php artisan migrate`すると、以下の3つのマイグレーションファイルが作成されます。

![スクリーンショット 2021-08-10 15.39.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/d78092af-6ca4-7b7d-689c-5492764d09d0.png)

データベースにも3つのテーブルが作成されます。

### booksテーブルとcategoriesテーブルのマイグレーションファイルの作成
ここから先ほど設計したbooksテーブルとcategoriesテーブルを作成していきます。

まずは以下のコマンドをターミナルで打ちましょう。

```
$ php artisan make:migration create_books_table --create=books
```

これでbooksのマイグレーションファイルが作成されます。

![スクリーンショット 2021-08-10 15.44.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/022077d5-bf0e-36b1-f7a7-a4f53f8b2d12.png)

以下のようにマイグレーションファイルを編集してください。

```php
<?php

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

class CreateBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->id('book_id');
            $table->bigInteger('user_id')->unsigned();
            $table->bigInteger('category_id');
            $table->string('book_name');
            $table->timestamps();

            $table->foreign('user_id')->references('user_id')->on('users')->onDelete('cascade');
        });
    }

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

```
編集が終わったら以下をターミナルで実行してください。

```
$ php artisan migrate
```
![スクリーンショット 2021-08-10 15.46.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/3c35caaf-5f8d-b200-29bb-d3d1f8011f3c.png)

上記のようにマイグレーションが成功するのを確認してください。
そして以下のようにデータベースに登録されていればbooksテーブルのマイグレーション成功です。

![スクリーンショット 2021-08-10 15.46.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/cccfd7c0-aca4-b346-6e11-73ea8d8e8812.png)

同様にcategoriesテーブルのマイグレーションも作成します。

```
$ php artisan make:migration create_categories_table --create=categories
```
作成されたマイグレーションファイルを以下のように編集してください。

```php
<?php

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

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id('category_id');
            $table->bigInteger('user_id')->unsigned();
            $table->timestamps();

            $table->foreign('user_id')->references('user_id')->on('users')->onDelete('cascade');
        });
    }

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

```

編集できたら、以下を実行してください。

```
$ php artisan migrate
```
ターミナルでマイグレーションの成功と、データベースにcategoriesテーブルが登録されていれば成功です。

これでマイグレーションファイルの作成は終わりです。

次に一覧画面を表示するためにモデルとコントローラーを作成します。

# モデルとコントローラーの作成
books、categoriesモデルとコントローラーを作成します。
【booksのモデル作成】

```
$ php artisan make:model Book
```
【booksのコントローラの作成】

```
$ php artisan make:controller BookController
```

app>Modelsの下にbook.phpが、app>Http>Controllersの下にBookController.phpが作成されます。

同様に、categoriesのモデルとコントローラーも作成します。

```
$ php artisan make:model Category
```

```
$ php artisan make:controller CategoryController
```

これで、books、categoriesテーブルのモデルとコントローラーが作成できました。

## ルーティングの設定
ルーティングを設定して、URLに飛んだらページを表示させるようにします。

routes>web.phpを編集します。

```php
<?php

use App\Http\Controllers\BookController;←追加
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

// 一覧画面表示用に追加
Route::get('/', [BookController::class, 'index']);
```

##Viewを作成する
一覧画面表示用にビューを作成します。

resources>Viewの下に「book」ファイルを作成してください。
![スクリーンショット 2021-08-10 16.29.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/bb76a8e2-0b79-1fdd-9046-47125f37630e.png)

#コントローラーの編集
bookController.phpを編集して、一覧画面を簡易的に表示させます。

bookControllerを以下のように編集してください。

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class BookController extends Controller
{
    public function index()
    {
        return view('book.index');
    }
}

```

そして、ビューが表示できるかテストするために、先ほどのbook>index.blade.phpを以下のように編集してください。

```php
<h1>本を管理</h1>
```

![スクリーンショット 2021-08-10 16.35.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/0169438c-9664-c49b-d205-70e194836b41.png)

画面表示できたら成功です。

##データベースのデータを表示させる
次のステップとして、データベースにあるデータを引っ張ってきてデータを表示させます。

まずは、データベースに任意のデータを挿入しましょう。

私は以下のようにデータを入れました。
※user_idは外部キーにしていると思うので、先にusersテーブルにデータを入れてからbooksテーブルにデータを入れないとデータを挿入できません。
![スクリーンショット 2021-08-10 16.43.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/6071672e-c9ac-d2ee-0aa2-44a3f7b9386b.png)

bookControllerを編集します。

```php
<?php

namespace App\Http\Controllers;

use App\Models\Book;←追加
use Illuminate\Http\Request;

class BookController extends Controller
{
    public function index()
    {
        $books = Book::all();
        return view('book.index', [
            'books' => $books,
        ]);
    }
}

```

resources>book>index.blade.phpを編集します。

```php
<h1>本を管理</h1>

@foreach ($books as $book)
  <p>ブックナンバー：{{ $book->book_id }}</p>
  <p>ブック名：{{ $book->book_name }}</p>
@endforeach
```

以下のように表示されれば成功です。

![スクリーンショット 2021-08-10 16.54.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/a23c9472-fd8e-9cae-927f-346bc03ae069.png)

以下のようにすれば、テーブル形式で表示させることが可能です。

```php
<h1>本を管理</h1>

<table>
  <thead>
    <tr>
      <th>ブックナンバー</th>
      <th>ブック名</th>
      <th>作成日</th>
    </tr>
  </thead>
  <tbody>
    @foreach ($books as $book)
    <tr>
      <td>{{ $book->book_id }}</td>
      <td>{{ $book->book_name }}</td>
      <td>{{ $book->created_at }}</td>
    </tr>
    @endforeach
  </tbody>
</table>
```

![スクリーンショット 2021-08-10 17.06.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/d7ef1830-7bb5-f7c8-4551-2e1dc83ed730.png)

##【レベルアップ】実務でコードを書くならこう書くべき！
上記の方法でも一覧画面は表示できるのですが、素人感満載のコードになります。

実務レベルでコードを書くなら、以下のようにコードを変更するべきです。
修正箇所は、book.phpとbookController.phpです。

・`$books = Book::all();`はモデルにロジックをかく
・`'books' => $books,`ここの部分はcompact関数を使うとスッキリする

理由：実務になると、コントローラーに書くコードは普通に1000行超えたりします。
今回は,`Book::all()`と非常に簡単なコードになりますが、実務では複雑なコードになるので、データベースからデータを取得するロジックでも10行とかになるんですよね。
なので、モデルにロジックを書かないと、コントローラーのコードが3000行とかになり、コードを追うのが大変になります。

それでは、コードをより実務レベルに近づけていきます。

### book.php　モデルの修正

```php
<?php

namespace App\Models;

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

class Book extends Model
{
    use HasFactory;

    // モデルに関連付けるテーブル
    protected $table = 'books';

    // テーブルに関連付ける主キー
    protected $primaryKey = 'book_id';

    /**
     * 一覧画面表示用にbooksテーブルから全てのデータを取得
     */
    public function findAllBooks()
    {
        return Book::all();
    }
}

```
モデルに一覧データを取得するロジックを書きました。

bookController.phpも以下のように修正しましょう。

```php
<?php

namespace App\Http\Controllers;

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

class BookController extends Controller
{
    public function __construct()
    {
        $this->book = new Book();
    }

    public function index()
    {
        $books = $this->book->findAllBooks();

        return view('book.index', compact('books'));
    }
}

```
__constructなどはlaravelの公式などで調べてください。

これで実務でも使えるコードが書けました。
もしこの記事が参考になったら、LGTMなどをお願いします。

暇なときに予定を探せるアプリ[yoteiPicker](https://yoteipicker.com/)をリリースしました。


https://www.kamome-susume.com/enginner-job-change-site/