LaravelからMySQLのデータをいじってみた

筆者スキルはLaravel素人。
主にある程度慣れているRuby on Railsと比較しながら進める。

## 環境
PHP 7.1.16
Laravel 5.6.26

### 初期設定
MySQLへのデータベース接続設定をする。
初期のままだとズレている模様。
下記の箇所をMySQLの設定に合わせて適宜編集する。
エンジンは指定しない場合はInnoDBとなるようで、nullのままで良さそう。

```:.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=root
DB_PASSWORD=
```

```php:config/database.php
        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'homestead'),
            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],
```

Railsの`db:create`のようなデータベースを作成するコマンドは無いので、データベースはMySQLのコマンドラインから作成する。

```bash
mysql -uroot -p
```

```sql
CREATE DATABASE `homestead` DEFAULT CHARACTER SET = `utf8mb4`;
```

### モデル生成

バグ一覧のためのモデル等の雛形を一式出力してみる。
`make:model`はRailsの`generate model`とだいたい同じだが、本当にモデルしか作らない。
Railsのように初期の列は指定はできない。
モデル名はRailsのようにうまい具合に大文字小文字や複数形を解釈してくれないので、作って欲しいモデル名をちゃんと指定する。
例えば`hoge`と指定したら（`Hoge`ではなく）`hoge`モデルができ、`hoges`と指定したら（`Hoge`ではなく）`hoges`モデルができる。
`-a`がだいたいRailsの`generate scaffold`相当で、モデルの他にコントローラ、マイグレーション、ファクトリーを生成してくれる。

```bash
php artisan make:model -a Bug
```

ただし本当に枠の作成のみで中身が無く、ルーティングもされていないので、このまま`http://localhost:8000/bugs`にアクセスしても何もできない。

個別にコントローラ（`-c`）、マイグレーション（`-m`）、ファクトリー（`-f`）を生成するオプションもあるが、あまり出番は無さそう。

次に生成されたマイグレーションを編集する。

```php:database/migrations/2018_07_04_025522_create_bugs_table.php
        Schema::create('bugs', function (Blueprint $table) {
            $table->bigIncrements('bug_id');
            $table->date('date_reported');
            $table->string('summary', 80)->nullable();
            $table->string('description', 1000)->nullable();
            $table->string('resolution', 1000)->nullable();
            $table->string('status', 20)->default('NEW');
            $table->string('priority', 20)->nullable();
            $table->decimal('hours', 9, 2)->nullable();
            $table->timestamps();
        });
```

下敷きにしたテーブルのDDLは以下の通り。

```sql
CREATE TABLE Bugs (
  bug_id SERIAL     PRIMARY KEY,
  date_reported     DATE NOT NULL,
  summary           VARCHAR(80),
  description       VARCHAR(1000),
  resolution        VARCHAR(1000),
  status            VARCHAR(20) NOT NULL DEFAULT 'NEW',
  priority          VARCHAR(20),
  hours             NUMERIC(9,2)
);
```

### マイグレーション実行

マイグレーションを流そうとすると以下のようなエラーが出るので、あらかじめ対処しておく。

```
Specified key was too long; max key length is 767 bytes
alter table `users` add unique `users_email_unique`(`email`)
```

```php:app/Providers/AppServiceProvider.php
:
use Illuminate\Support\Facades\Schema;
:
    public function boot()
    {
        Schema::defaultStringLength(191);
    }
:
```

その後、マイグレーションを実行。

```bash
php artisan migrate
```

### データを操作してみる
`rails console`に相当するコンソールを起動する。

```bash
php artisan tinker
```

コンソールから適当にデータを操作してみる。

```php
DB::table('bugs')->insert(
    ['date_reported' => '2018-05-06', 'summary' => '🍺', 'description' => '😃', 'resolution' => '😂', 'status' => '👌', 'priority' => '⏬', 'hours' => 1.2]
)
DB::table('bugs')->where('bug_id', 1)->update(['hours' => 1.5])
DB::table('bugs')->where('bug_id', 1)->first()
# => {#2881
#      +"bug_id": 1,
#      +"date_reported": "2018-05-06",
#      +"summary": "🍺",
#      +"description": "😃",
#      +"resolution": "😂",
#      +"status": "👌",
#      +"priority": "⏬",
#      +"hours": "1.50",
#      +"created_at": null,
#      +"updated_at": null,
#    }
```

データベース上でもデータが入っている事が確認できた。

![スクリーンショット 2018-07-04 18.24.07.png](https://qiita-image-store.s3.amazonaws.com/0/9104/e037ad33-1c19-2a8e-0999-4db5c40c54aa.png)

## 参考
- [Laravel 5.4: Specified key was too long error - Laravel News](https://laravel-news.com/laravel-5-4-key-too-long-error)
- [データベース：クエリビルダ 5.6 Laravel](https://readouble.com/laravel/5.6/ja/queries.html)