LaravelでDBのテーブルやカラムを編集してみた

##はじめに
laravelを使いDBのテーブルやカラムを作成したり削除、追加などをしてみたので備忘録として書きました。お役に立てれば幸いです。

間違い等がございましたら、ご指摘のほどよろしくお願い致します。(お手柔らかにお願いします...)

##目次
* 開発環境
* マイグレーションについて
* DB接続の確認
* マイグレーションファイルの作成
* カラム構成の編集
* マイグレーションファイルの実行
* カラムの追加
* カラム名の変更
* カラムの削除
* ロールバック
* リセット
* リフレッシュ
* カラムのデータ型の変更
* 参考文献

##開発環境
MAMP
MySQL 5.7
laravel 6.0
php 7.4

##マイグレーションについて

``マイグレーションとは``
PHPフレームワーク内でのスクリプトを用いてデータベース情報を管理していく事です。
マイグレーションは基本的にLaravelのスキーマビルダ(Schema)と一緒に使い、アプリケーションのデータベーススキーマを作成するために使用します。また、後からカラムを追加したり一つ前の状態のデータに戻すこともできます。

ちなみに、LaravelのSchemaファサードは、テーブルの作成や操作をサポートしてるデータベースシステム全部に対しサポートします。


``注意``マイグレーション機能の導入前に、LaravelがDBに接続出来ている事が最低限必要なので、接続していない場合は、.envファイルを開いて接続情報を記載してください。

```:MySQL
DB_CONNECTION=mysql
DB_HOST=127.0.0.1     # ホスト名
DB_PORT=3306          # ポート番号
DB_DATABASE=###       #データベース名
DB_USERNAME=###       # ユーザ名
DB_PASSWORD=###       # パスワード
```


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

```
$ php artisan make:migration create_[テーブル名]_table  --create=[テーブル名]
```
上記のように、Artisanコマンドを使って実行すると、Database/migrationsにマイグレーションファイルが作られます。
今回は本のデータに関するテーブルを作成しようと思うので、``php artisan make:migration crete_books_table  --create=books``を実行してみたいと思います。

このコマンドを実行する際に気をつけて欲しい点があります。

* 作成するマイグレーションファイルですが、基本的には作成するテーブル１つにつき１つのマイグレーションファイルを作成します。

* ``create_``と``_table``の箇所は書かなくても良いですが、何の為のファイルかを一目で分かるように書いておくのが無難です。(laravelの公式の書き方に倣っています)

* crete_``books``_tableのように、テーブル名は複数形で作るようにしましょう。理由は、ここで記述した名前(books)がそのままテーブル名になるからです。

* ここでの名前は、生成するマイグレーションファイルのクラス名に反映されるので、そのことを考慮した上で名前をつけましょう。

また、make:migrationコマンドには``--create``オプション引数が用意されています。
``--createオプション``は、Schemaクラスのメソッド（テーブルを新たに作成するcreateメソッド）を指定しています。つまり、テーブルを新たに作成するマイグレーションファイルを作成するコマンドの実行時に指定するオプションです。

```
$ php artisan make:migration create_books_table --create=books(テーブル名)
と記述すると、Schemaファサードのcreateメソッドを指定できる
```

上記の注意点を踏まえて生成されたマイグレーションファイルを見てみると、下記の様な構成でファイルが作られています。ざっくりと説明すると``public function up(){}``でテーブルのカラム構成を決め、``public function down(){}``で作成したテーブルを崩す役割を担っています。(間違っていればご指摘ください)

```php:2021_01_28_121411_crete_books_table.php

<?php

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

class CreteBooksTable extends Migration
{//クラス名に注目してください。先ほど述べたようにクラス名に反映されいています。
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('books');
    }
}
```
それぞれの役割を詳しく見ていきます。
##カラム構成の編集(public function up(){};)
```php
public function up()
{
 Schema::create('books', function (Blueprint $table) {
       $table->bigIncrements('id');
       $table->string('title',200);
       $table->string('name',100);
       $table->string('comment',200);
       $table->integer('price');
       $table->timestamps();
    });
}
```
上述で使用している、``Schema::create``がSchemaファサードのcreateメソッドであり、新しいデータベーステーブルを作成する際に使用します。``$table->string();``などは**スキーマビルダ**と呼ばれていて、テーブルを構築する時に使用するさまざまなカラムタイプを指定できます。
Laravelのマイグレーションファイルではstringやinteger以外にも指定できるデータ型があるので、学習時によく使用した（今後も使用するであろう）ものを下記に一覧表で記載しておきます。



###カラムタイプ一覧
|コマンド|説明|
|:---:|:---:|
|$table->bigIncrements('id');|符号なし、BIGINTを使用したオートインクリメント(自動増分)ID（主キー）|
|$table->boolean('confirmed');|BOOLEANカラム|
|$table->char('name', 100);|オプションの文字長を指定するCHARカラム|
|$table->date('created_at');|DATEカラム|
|$table->text('description');|TEXTカラム|
|$table->timestamps();|NULL値可能なcreated_atとupdated_atカラム追加|
|$table->ipAddress('visitor');|IPアドレスカラム|
|$table->integer('votes');|INTEGERカラム|
|$table->json('options');|JSONフィールド|

また、Laravelではカラムに**装飾子**を付け加えることができます。
先ほど解説した記述文にそのまま -> (アロー演算子)で繋げて記述するだけです。

```php
$table -> string('email') -> unique();
//メールアドレスの重複をなくす
$table -> string('email') -> unique() -> nullable();
//カラムにnullを設定できるようにする
```
###装飾子一覧
|装飾子|説明|
|:---:|:---:|
|->autoIncrement()|整数カラムを自動増分ID（主キー）へ設定|
|->after('column')|指定カラムの次に他のカラムを設置(MySQLのみ)|
|->charset('utf8')|カラムへキャラクタセットを指定(MySQLのみ)|
|->collation('utf8_unicode_ci')|カラムへコロケーションを指定(MySQL/SQL Serverのみ)|
|->comment('my comment')|カラムにコメント追加(MySQL/PostgreSQLのみ)|
|->default($value)|カラムのデフォルト(default)値設定|
|->first()|カラムをテーブルの最初(first)に設置する(MySQLのみ)|
|->nullable($value = true)|デフォルトで）NULL値をカラムに挿入する|
|->storedAs($expression)|stored generatedカラムを生成(MySQLのみ)|
|->useCurrent()|TIMESTAMPカラムのデフォルト値をCURRENT_TIMESTAMPに指定|
|->unsigned()|整数カラムを符号なしに設定(MySQLのみ)|
|->virtualAs($expression)|virtual generatedカラムを生成(MySQLのみ)|

##マイグレーションファイルの実行
```
$ php  artisan migrate
```
上記のコマンドを実行すると、マイグレーションファイルに設定された形でテーブルが作られます。

また、テーブルを作成するとidに``unsigned``という属性が付与され、意味は符号なし、マイナスの値は存在しないと示しています。

今回の記事では、リレーションを使いませんが、リレーションを組むときに、親テーブルと子テーブルとの間でマイナス値があったりなかったりするとエラーが発生するので、予めマイグレーションファイルでカラムの詳細を決める時に、下記のように指定することでマイナス値を排除しておくことをオススメします。

```php
 $table->tinyInteger('book_id')->unsigned();
//or
$table->unsignedTinyInteger('book_id');
```

また、migrateコマンドには上記の設定を反映するコマンド以外にも、様々な操作を行えます。
では、

1. カラムの追加
2. カラム名の変更
3. カラムの削除
4. ロールバック
5. リセット
6. リフレッシュ
7. カラムのデータ型の変更

の操作について触れてみたいと思います。


##カラムの追加

基本的に、カラムの追加や編集をする場合は、上記で作成したマイグレーションファイルを編集し、下記のように``php artisan migrate``に``:refresh``を付けて再度マイグレーションを実行します。

```
$ php artisan migrate:refresh
```

しかし、私は変更した過程をマイグレーションファイルとして記録しておきたいので、``tableオプション``に変更するテーブル名を指定し、新たにマイグレーションファイルを作成しています。
従って、この記事では、新しいマイグレーションファイルを作りつつテーブルを変更しています。

今回作成したテーブルに出版社名のカラムを追加してみたいと思います。

新たにカラムを追加する際は、

```
$  php artisan make:migration add_publisher_to_books_table --table=books
```
のように記述します。作成時との変更点は、オプション引数が``--table=テーブル名``になっている点と、``add_publisher_to_books_table``の２つです。

* ``--table``は、テーブル構造を変更する場合の決まり文句みたいなものです。追加する際は、記述してください。

* ``add_publisher_to_books_table``は、database/migrations下で作られたファイルの中でクラス名としても使われるので、何故、そのファイルが作成されたのかを一目で分かるように変更しています。

上記のコマンドを実行すると、下記のようなファイルが作成されます。

```php:2021_01_28_122256_add_publisher_to_books_table.php

<?php

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

class AddPublisherToBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            //新規作成時はSchema::create
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('books', function (Blueprint $table) {
            //
        });
    }
}
```
マイグレーションファイルが作成されたら、``public function up(){}``に追加するカラムを記述します。

```php
public function up()
{
Schema::table('books', function (Blueprint $table)
{
 $table->string('publisher',50)->after('title');
/*$table->string('publisher',50);の場合、カラムの最後に追加されるので、
追加したい順を決める場合、->after('カラム名');と指定することで
指定したカラム名の次に追加される*/
  });
}
```
追加するカラムの記述が終わり次第、``php artisan migrate``を実行するとカラムが追加される。

##カラム名の変更

まず、設定として

```
$ composer require doctrine/dbal
```
とコマンドを入力して、composerで"doctrine/dbal"をインストールして下さい。laravelはデフォルトでカラム名の変更や削除ができません。(何でや...調べてみます)

``注意``上記のコマンド入力後、エラーが発生する場合

```
$ composer require "doctrine/dbal:2.*"
```
のように記述して下さい。理由は、下記リンクの記事が分かりやすかったので覗いてください。

>[[laravel] doctrine/dbalを入れたのに「Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found」と言われる]
(https://qiita.com/snbk/items/803aea10773052629a45)

カラム名を変更する為には``renameColumnメソッド``を使用します。

今回は、booksテーブルのnameカラムをauthorに変更します。

下記のようにマイグレーションファイルを作成します

```
$ php artisan make:migration rename_変更前のカラム名_変更後のカラム名_テーブル名_table --table=テーブル名
```
と記述する。

```
$ php artisan make:migration rename_name_author_books_table --table=books
```
実行すると、下記のようにマイグレーションファイルが作成され、``public function up(){}``で``renameColumnメソッド``を使い、変更したいカラム名を指定する。その後、``php artisan migrate``コマンドを実行することで変更が反映される。

```php

    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
        $table->renameColumn('name','author');
//$table->renameColumn('変更する前のカラム名', '変更した後のカラム名');
        });
    }
```

##カラムの削除
カラムを削除する為には、``dropColumnメソッド``を使用します。

毎度お馴染みのようにマイグレーションファイルを作成します。

```
$ php artisan make:migration drop_削除するカラム名_テーブル名_table --table=テーブル名
```
今回は下記のようにコマンドを使います。

```
$ php artisan make:migration drop_comment_books --table=books
```
コマンドを実行後、マイグレーションファイルが作成され、下記のように``public function up(){}``で``dropColumnメソッド``使い、削除するカラムを指定する。その後、``php artisan migrate``コマンドを実行することで変更が反映される。


```php

    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            $table->dropColumn('comment');
          //$table->dropColumn('削除したいカラム名');
        });
    }
```
##ロールバック
カラムを追加したがやっぱり一つ前に戻りたい、migrateの状態を一つ前に戻す場合にロールバックコマンドを使います。正確に言えばマイグレーションファイルのdown()に記述された処理を実行していきます。


```
$ php artisan migrate:rollback
//1つ前の状態に戻る
```
上記のコマンドは、stepオプションをつけることによって、``--step=戻りたい数``を記述することで、いくつ前に戻すかを指定することができる。

```
$ php artisan migrate:rollback --step=2
//2つ前に戻ることになる
```

``注意`` ``php artisan migrate:rollback``を使う場合、追加時に作成したマイグレーションファイルで、追加したカラムを``public function down(){}``で``dropColumnメソッド``を使い、下記のように記述する必要がある。※下記のマイグレーションファイルはロールバックを説明する為に別途作成したファイルなのでカラム名commentが重複しています。申し訳ございません。

```php:別途作成、記事で作成したカラム(comment)とは関係ありません
<?php

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

class AddCommentToBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            $table->string('comment',200);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('books', function (Blueprint $table) {
            $table->dropColumn('comment');
        });
    }
}
```
``php artisan migrate:rollback``を実行後、``php artisan migrate:status``で状態を確認すると、下記のようにカラムcommentが追加される前の状態に戻っている。

|Ran?| Migration|Batch|
|:---:|:---|:---|
|Yes|2014_10_12_000000_create_users_table|1|
|Yes|2014_10_12_100000_create_password_resets_table|1|
|Yes|2019_08_19_000000_create_failed_jobs_table|1|
|Yes|2021_01_27_203453_create_posts_table|1|
|Yes|2021_01_27_203607_create_comments_table|1|
|Yes|2021_01_28_121411_crete_books_table|1|
|Yes|2021_01_28_174256_add_publisher_to_books_table|2|
|Yes|2021_01_28_185459_rename_name_author_books_table|3|
|No|2021_01_28_211805_add_comment_to_books_table|9|

##リセット
```
$ php artisan migrate:reset
```
上記のコマンドで、今まで行ったマイグレーションを全てロールバックし初期状態のデータベースに戻します。正確に言えばマイグレーションファイルのdown()に記述された処理を実行していきます。
ロールバックとの違いは、**存在するすべてのマイグレーションファイルのdown()が実行される**点です。




##リフレッシュ
```
$ php artisan migrate:refresh
```
上記のコマンドで、全てのマイグレーションをリセットし初期状態に戻した後、``migrateコマンド``を行います。
また、リフレッシュもロールバックと同じように、``stepオプション``をつけることによって、指定した回数分だけ戻ってmigrateすることができます。
※``php artisan migrate:refresh``は、``php artisan migrate:reset``してmigrateするのと同じです。

##カラムのデータ型の変更
booksテーブルのcommentカラムをsrting型からtext型に変更してみます。

コマンドは下記のように記述してマイグレーションファイルを作成します。

```
$ php artisan make:migration change_comment_books --table=books
```
マイグレーションファイルでは、``public function up(){}``で``changeメソッド``を使い、カラムのデータ型を変更しています。

```php
    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            $table->text('comment')->change();
        });
    }
```
***

##参考文献

* [laravel ドキュメント](https://readouble.com/laravel/)
* [laravel 学習帳](https://laraweb.net/)
* https://www.sitepoint.com/how-laravel-facades-work-and-how-to-use-them-elsewhere/
* [【Laravel】わりとよく使うArtisanコマンド集](https://qiita.com/sola-msr/items/a09b857c5e7f7c88d01d)