【Laravel×MySQL】 モデル・テーブルの作成＋カラムの変更

# はじめに
Laravelをインストールしたあとの操作を、備忘として残していきます。初心者のため修正・指摘・アドバイスなどありましたらご教授いただけるととても嬉しいですm(__)m。

**▼作っているもの**
レシピ投稿サイトのようなもの。DBにはrecipesというテーブルを作り、レシピを投稿していくのを想定。

**▼開発環境**
・CentOS 6.10(virtualboxとvagrantでローカル開発環境)
・MacBook (macOS Catalina バージョン10.15.2)
・PHP 7.1.33
・Laravel Framework 5.8.38
・MySQL バージョン5.7.31

**▼前提**
・MySQLをインストール済み。
・Composerを使ってLaravelをインストール済み。

# 1. LaravelでMySQLに接続
MySQLのインストールがまだの場合は用意しておく。Laravelをインストールした時に生成される.envファイルを編集する。適切に接続を定義することで、Laravelからデータベースを操作できるようになる。

### ⓪[準備]MySQLでDBの作成
（例）myappという名前のDBの作成（ユーザ名はdbuser,パスワードはpass）
```mysql -u root``` --> ```create database myapp;``` --> ```grant all on myapp.* to dbuser@localhost identified by 'pass';```

### ①.envファイルの編集
.envファイルを開き、[準備]で作成したDB名、ユーザ名、パスワードの値に変更する。

```.env
DB_CONNECTION=mysql /*接続に使用するドライバー名。mysqlやsqlite3など。*/
DB_HOST=127.0.0.1 
DB_PORT=3306
DB_DATABASE=myapp /*DB名*/
DB_USERNAME=dbuser /*ユーザ名*/
DB_PASSWORD=pass /*パスワード*/
```
❓DB_HOSTとDB_PORTはそのままでも接続できたが理屈がわからない…いつかわかったら追記します(きっと)。

### ②[config]フォルダ > app.phpファイルの編集
app.phpファイルを開き、```timezone```と```locale```の箇所だけ変更。ちなみにdatabase.phpファイルにもmysqlの記述があるが、.envファイルを変更しておけばそちらが適用されるので何も変更しなくてOK。

```app.php
'timezone' => 'Asia/Tokyo',
'locale' => 'ja', 
```

# 2. モデルとテーブルを作る <新規作成>
### ①モデルとそのmigrationファイルを作る

```
php artisan make:model Recipe(モデル名) --migration
```

### ②①で作成したmigrationファイルを編集
[database]フォルダの、[migrations]フォルダ内に作られている。

```20XX_XX_XX_XXXXXX_create_XXX_table.php
public function up()
    {
        Schema::create('recipes', function (Blueprint $table) {
            $table->bigIncrements('id'); /* 主キー */
            $table->string('title');
            $table->text('body'); /* 説明 */
            $table->string('img');
            $table->string('age'); /* おもちゃの対象年齢 */
            $table->string('material'); /* 材料 */
            $table->string('level'); /* 作る時の難易度 */
            $table->timestamps();
        /* データの型(bigIncrementsやstring,text,timestampsなど)の説明は
　　　    　次の項目で書きます！ */
        });
    }
```

### ③②のファイルを保存し実行

```
php artisan migrate
```

### ④確認
▷migrationファイル（②のmigrationファイルがRan?Yesに!!）

```
php artisan migrate:status
+------+-------------------------------------------------+-------+
| Ran? | Migration                                       | Batch |
+------+-------------------------------------------------+-------+
| Yes  | 2020_08_15_085940_create_recipes_table          | 1     |
+------+-------------------------------------------------+-------+
```

▷作られたテーブル構造（②の編集内容が反映されてる!!）

```
[vagrant@localhost ~]$ mysql -u root  // MySQLにログイン
mysql> use データベース名;  // DBを選択
mysql> desc テーブル名;  // テーブルの詳細を表示
+------------+---------------------+------+-----+---------+----------------+
| Field      | Type                | Null | Key | Default | Extra          |
+------------+---------------------+------+-----+---------+----------------+
| id         | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255)        | NO   |     | NULL    |                |
| body       | text                | NO   |     | NULL    |                |
| img        | varchar(255)        | NO   |     | NULL    |                |
| age        | varchar(255)        | NO   |     | NULL    |                |
| material   | varchar(255)        | NO   |     | NULL    |                |
| level      | varchar(255)        | NO   |     | NULL    |                |
| created_at | timestamp           | YES  |     | NULL    |                |
| updated_at | timestamp           | YES  |     | NULL    |                |
+------------+---------------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
```

# ■カラムのデータ型
**※個人的によく使うものだけ抜粋してます**
・**bigIncrements**('id') ... *符号なしINT*を使った自動増分ID(主キー)。[incrementsとの違い](https://qiita.com/fuubit/items/17f3eb306c64ede163d2)
・enum('カラム名', ['定数', '定数']) ... ENUMカラム
・**string**('カラム名') ... VARCHARカラム。第2引数で長さ指定も可、デフォルト255文字。[charとの違い](https://qiita.com/oseibo/items/c589430bdb00c6ab4922#:~:text=CHAR%E5%9E%8B%20%E3%81%AF%E3%80%81%20%E9%83%B5%E4%BE%BF%E7%95%AA%E5%8F%B7,%E6%80%A7%E3%81%AE%E3%81%82%E3%82%8B%E3%82%82%E3%81%AE%E5%90%91%E3%81%91%E3%80%82)
・**text**('カラム名') ... TEXTカラム
・dateTime(カラム名) ... 日時カラム。dateは日付のみ、timeは時間のみ。
・**timestamps**() ... created_atとupdate_atカラム
[▶︎もっと見たい方はこちらの記事](https://qiita.com/Otake_M/items/3c761e1a5e65b04c6c0e)

# ■カラムのオプション・インデックス
**※あとから変更する時はdoctrine/dbaのインストールが必要**
**▷オプション(1) defaultを設定**
```$table->データ型('カラム名')->default(デフォルトの値や文字列);```
（例）$table->string('user_id')->default(0); //NULL,など

**▷オプション(2) NULLを許容／許容しない**
```$table->データ型('カラム名')->nullable();``` //許容
```$table->データ型('カラム名')->nullable(false);``` //許容しない

**▷オプション(3) 符号なし属性**
```$table->データ型('カラム名')->unsigned();```

**▷オプション(4) 追加カラムの位置指定※MySQLのみ**
```$table->データ型('カラム名')->after('カラム名');```

**▷インデックス(1) カラムにインデックスを追加**
```$table->データ型('カラム名')->index('カラム名');```

**▷インデックス(2) カラムにユニークキーを追加**
```$table->データ型('カラム名')->unique('カラム名');```


# 3-1. テーブルのカラムを追加したい <変更>
recipesテーブルに、誰が投稿したのかを示すuser_idカラムを入れ忘れた！
最初にテーブルのカラムを作成したmigrationファイル(上の②のファイル)を編集してから```php artisan migrate```としても良いが、~~せっかくなのでバージョン管理っぽいことをしてみたい。~~それだとロールバック(このケースだと、カラム追加を取り消すこと)ができない。なので、

**①新しいmigrationファイルを作る**

```
php artisan make:migration add_user_id_to_recipes_table --table=recipes
```
※既存のテーブルに変更を加える場合には、```--table``` オプションを使って、テーブル名を指定する。

**②①で作成したmigrationファイルを編集**
[database]フォルダの中の、[migrations]フォルダ内にある。

```2020_08_16_070604_add_user_id_to_recipes_table.php
public function up()
    {
        Schema::table('recipes', function (Blueprint $table) {
            //カラムの追加(シンプル)
            /* $table->integer('user_id'); */

            //カラムの追加+オプション(欲張りver.)
            //✅■カラムのオプション・インデックス（オプションの詳細について記載）
            $table->integer('user_id')->unsigned()->default(0)->after('level');
        });
    }

    public function down()
    {
        Schema::table('recipes', function (Blueprint $table) {
            $table->dropColumn('user_id'); //カラムの削除
        });
    }
```

**③②のファイルを保存し実行**

```
php artisan migrate
```

**④確認**
・```php artisan migration:status```
・MySQLにログイン・DBの選択後、```desc テーブル名;```
（詳細は　■モデルとテーブルを作る　に記載)


# 3-2. カラムの型を変更したい <変更>
最初に作ったlevelカラムは、1,2,3...といった整数を想定しているので、最初に設定したstring型から変更したい！あと、全てのカラムで```not null```としたい(値が入っていないとエラーを返したい)。
**⓪[doctrine/dbal インストール(準備)]()**
**①migrationファイルの作成**
```php artisan make:migration マイグレーションファイル名 --table=テーブル名```
**②①で作成したmigrationファイルの編集**
・up()には今回変更したい処理、down()にはup()と逆の処理を書く
**③②のファイルを保存し実行**
```php artisan migrate```
**④確認**
・```php artisan migration:status```
・MySQLにログイン・DBの選択後、```desc テーブル名;```
（詳細は　■モデルとテーブルを作る　に記載)

# 3.(まとめ) 何かしら変更したい <変更>

- **カラムを追加したい**　（例）user_idというカラムを追加したい
- **カラムのデータ型を変更したい**　（例）string型からinteger型にしたい
- **カラム名を変更したい**　（例）nenrei から age にしたい
- **defaultなどのオプションをつけたい**　（例）デフォルト値は0としたい
- **【発展】新しいテーブルを作りたい**
- **【発展】テーブル名を変更したい**

✅データ型の詳細については、**■カラムのデータ型** を参照
✅オプションの詳細については、**■カラムのオプション・インデックス**　を参照

↓基本的な流れ
### ⓪doctrine/dbal パッケージを導入(準備)
デフォルトのままでは型やカラム名の変更をしようとmigrationファイルを実行すると、下記のようなエラーが。カラムの変更を行う場合は、["doctrine/dbal"パッケージを導入する]()必要があるみたい。
```RuntimeException  : Changing columns for table "recipes" requires Doctrine DBAL; install "doctrine/dbal".```

### ①migrationファイルの作成
```php artisan make:migration マイグレーションファイル名 --table=テーブル名```
### ②①で作成したmigrationファイルの編集
・up()には今回変更したい処理、down()にはup()と逆の処理を書く

```2020_08_31_000000_XXXXXX.php
 public function up()
    {
        Schema::❶table('テーブル名', function (Blueprint $table) {
            /* カラムの追加 */
            $table->string('user_id');
            /* カラム名の変更 */
            $table->renameColumn('nenrei', 'age');
            /* 型の変更 */
            $table->string('age')->default(NULL)->change();
            /* nullを許可する、に変更 */
            $table->string('fax_name')->nullable()->change();
        });
    }

 public function down()
    {
        Schema::table('recipes', function (Blueprint $table) {
            // カラムの削除 
            $table->dropColumn('user_id');
            // カラム名を戻す
            $table->renameColumn('age','nenrei');
            // 型を戻す
            $table->smallInteger('year_birth_no_name')->change();
            // nullを許可しない、に変更
            $table->string('fax_name')->nullable(false)->change();
        });
    }
```


#### 【発展】テーブルの新規作成は```create```
```Schema::create()メソッド``` を使う。up()にそのテーブルに入れたいカラムを書いていく。down()には```dropIfExists('テーブル名');```と書く。

```.php
public function up()
    {
        Schema::create('recipes', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }
```

#### 【発展】テーブル名変更は```rename```
```Schema::rename()メソッド``` を使う。up()にrename('変更前のテーブル名', '変更後のテーブル名')を書く。dowon()はrename()の()の中身を逆にする。

```.php
public function up()
    {
        // Schema::rename('変更前のテーブル名', '変更後のテーブル名');
        Schema::rename('sample_a', 'sample_b');
    }
```

# ■操作後の確認・ロールバック
**▶︎実行したmigrationファイルの確認**
```php artisan migrate:status```

**▶︎テーブルでカラムの確認**
```mysql -u root```でMySQLにログイン--->```use DB名```でDBを選択--->```desc テーブル名```で確認。

**▶︎ロールバック**
```php artisan migrate:rollback --step=2```
```--step```オプションをつけると、巻き戻す数を限定できる。上の例だと2つをロールバックする。```migrate:reset```コマンドで、全てのマイグレーションをロールバック。