Laravel5.5でDBのCRUDを実装してみる

LaravelのDBとの連携方法がまったくわからなかったのでいろいろ調べてました。
メモ書き程度の資料は見つかるものの、根本的なところがわかってないので断片的な記述では理解できないのです……。

バージョンが違うものなら見つかりましたが、けっこうバージョンごとにいろいろと変更されていて、あんまりアテになりません。

バージョン違うんだからアテにするなと言われてしまえばその通りなんですが。

しかも5.5に関しては新しいものなのか、ドットインストールでも有料コンテンツになってるし、うーん、この……。
とか思ってたら詳細な資料がQiitaに転がってました。


#実践
基本的にこれを見てたらできました。

- [Laravel 5.5で基本的なCRUDを作る - Qiita](https://qiita.com/sutara79/items/ef30fcdfb7afcb2188ea)

#挫折ポイント
##User.phpの参照の付け忘れ
途中、ここ（[Laravel5.5: usersのCRUD機能を実装する - Qiita](https://qiita.com/sutara79/items/cd4371b246b44a2cf87f)）でUser.phpにIluminate/Http/Requestsを付け忘れてハマりそうになりました。

デフォルトでは付いてない……？か、あるいはいろいろいじっている間に消してしまったのかもしれません。

###参考資料
- [Class App\Http\Controllers\Request does not exist.](https://laracasts.com/discuss/channels/general-discussion/class-apphttpcontrollersrequest-does-not-exist)

エラーメッセージを調べて出てきたのがこれでした。

しかし、これをつけるとなんでこのエラーメッセージが解消されるのかがまったく理解できません。
そもそもRequestsなんてディレクトリがないんですけど……。
illuminateとかいうものについて少し勉強する必要がありそうです。

- [Laravelソースコードの歩き方](https://kore1server.com/326)

これが結構詳しかったです。


##registerじゃなくてusers.create
よくわからないポイント。
画面上、ユーザーの登録画面のルーティングはregisterになっているんですが、設定した部分だけだとどうやってもusers/createになります。
とはいえこの登録画面はUserControllerが勝手にやってる部分なので、


##変数名はpostじゃないといけない
エラーではないんですが。

- [Laravel5.5: postsのCRUD機能を実装する - Qiita](https://qiita.com/sutara79/items/4d4854d0f1137aed20d4)

こちらの手順の実施中、一番最後のdestroyを実装するところで、こんな感じで変更します。

    destroy($id)

    ↓

    destroy(Post $post)

これ、変更しなければdestroyなんてねーよとエラーになります。
これは想定通りです。

**でも、変数名が$postでないと反応しなかったのは意味がわかりませんでした。**

\$idではダメ。\$id2、\$posT、\$POST、いろいろ試しましたが動きませんでした。
なんでだろう。

##ペジネーションビュー
あとでお世話になりそうなのでメモ

- [データベース：ペジネーション 5.4 Laravel](https://readouble.com/laravel/5.4/ja/pagination.html#customizing-the-pagination-view)


##DBの定義変更後にmigrateできなくなる
- [Laravel5.5: postsとusersを関連させる - Qiita](https://qiita.com/sutara79/items/9e57e7af03b65e0d6047)

これをしてたらエラー。
定義変更後、

    > php artisan migrate:refresh --seed

でエラー。

```

  SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'posts' alre  
  ady exists (SQL: create table `posts` (`id` int unsigned not null auto_incr  
  ement primary key, `title` varchar(255) not null, `body` text not null, `cr  
  eated_at` timestamp null, `updated_at` timestamp null) default character se  
  t utf8mb4 collate utf8mb4_unicode_ci)                                        

```

postsはもうあるよバーカバーカとのこと。
**mysqlから直接postsをdropしたら動くようになりました。**

一発目、ちょっとつづりを間違えてたところがあったまま実行してしまったので、それで何かゴミが残っちゃったっぽいですね。

あと、phpStorm上だとmigrationに追加したunsignedとかreferencesとかが警告吐くんだけど気にしないでいいのかな……よくわかりません。
とりあえず動いてます。


##wgetでgitからファイルを取得
中盤くらいから、gitからファイルを落としてねという指示が多くなります。
ファイルを作って、内容をコピーして……でもいいんでしょうが、楽な方法はないかなということで以下の方法が良さそうです。

- [GitHub - githubからファイル単体をclone(DL)できる？(14124)｜teratail](https://teratail.com/questions/14124)

cloneではないですが、wgetという関数で取得できるみたいです。
こんな感じ。

    wget https://raw.githubusercontent.com/.../XXX.php

URLは、githubの画面にあるRawボタンを押すとテキスト表示になるので、そのページのURLを利用します。


##確認付きのdeleteボタン
usersのshow.blade.phpの修正で詰まりました。

この画面、二箇所にdeleteボタンがありましたね。
一つはUserそのもの、もう一つは紐付いている個々のPostごとの削除ボタンです。
最初に片方だけしか直していなくて、難儀しました。
画面が表示されないとボタンが複数あることも気付けないし……いや、覚えておけって話なんですけども。


##registerがログイン必須になる?（気のせいだった）
- [Laravel5.5: ログイン機能を追加する - Qiita](https://qiita.com/sutara79/items/fdbfbf2a8f86f7d8f7fb)

これをやってみたら、ログインしていない状態でregisterにアクセスするとloginにリダイレクトされるようになりました。

……と思ったら、この手順をするまではregisterを作成していない状態だったので、registerではなくusers/createを指定していたことを忘れていました。
my.blade.phpから、users.createで指定していたところをregisterに変更したら問題なく動くようになりました。


##関数のコメントを生成する（phpStorm）
Visual Studioはよく使ってるんですけどphpStormだって似たようなことできるだろと調べたらやっぱりできるんですね。知ってた！

- [phpstormでメソッドのコメントtips - Qiita](https://qiita.com/soramugi/items/0501e4f9e46a69f30fb8)

作成した関数のすぐ上の行で/**と入力してエンターを押すとできるらしくて、やってみたらちゃんとできました。


##php artisanが不発する
- [Laravel5.5: 日本語のパスワードリセット用のメールを送信する - Qiita](https://qiita.com/sutara79/items/0ea48847f5565aacceea)

ここでtinker入れようとしたら怒られました。

    Could not open input file: artisan

何事……と焦りましたが、どうやら単にディレクトリが違うってことみたいです。

- [LaravelでCould not open input file: artisanって言われたら - Qiita](https://qiita.com/saku_tto_chan/items/724f00d6495deaceabaf)

Laravel直下で起動したら普通に動きました。

##phpunit
テストのところ。

- [Laravel5.5: テストの基本 - Qiita](https://qiita.com/sutara79/items/f8c8313c97ce4d2febc2)

phpunitの呼び出しコマンドがバックスラッシュになっているんですけど、普通のスラッシュで動きました。

```
$ vendor\bin\phpunit
vendorbinphpunit: command not found

$ vendor/bin/phpunit
You need to set up the project dependencies using Composer:

    composer install

You can learn all about Composer on https://getcomposer.org/.
```

動いたんですけど、どうやらインストールが必要みたい？

が、composer install --devとかやっても更新対象がないと言われてしまいます。
composer.jsonにもphpunitの記述自体はありましたので、設定はされているようですが……。

いろいろ調べて、composer自体の更新をしている手順を発見しました。

- [PHPUnitを使ってみる - Qiita](https://qiita.com/suisuina/items/5427b78a62e6d9bb0c86)

試しにやってみたら当たりだったみたいで、動くようになりました。

```
$ vendor/bin/phpunit --version
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
```

これでいけるか……!?

###エラー。
と思ったら、今度は参考資料で挙げられているのと同じエラーが。


```
$ composer test
> phpunit
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

F.                                                                  2 / 2 (100%)

Time: 1.24 seconds, Memory: 12.00MB

There was 1 failure:

1) Tests\Feature\ExampleTest::testBasicTest
Expected status code 200 but received 404.
Failed asserting that false is true.

/home/vagrant/code/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:78
/home/vagrant/code/laravel/tests/Feature/ExampleTest.php:19

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
Script phpunit handling the test event returned with error code 1
```

ログを見ろと資料にはありましたがログファイルがありません……。
200のところに404が返ってきてるよと。

該当のテストケースを確認してみるとこんな感じでした。

    $response = $this->get('/');

ルートですね……取れても良さそうですが。
試しに直接URLを指定したところ成功しました。

    $response = $this->get('http://homestead.test/');

見返してみると資料ではXAMPPを利用しているみたいなので、その辺でエラーになってしまうのかな……？
と思いつつ、スルーすることにします。


###--filter
```
$ composer test -- --filter Feature\\ExampleTest 
> phpunit '--filter' 'Feature\ExampleTest'
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.



Time: 147 ms, Memory: 6.00MB

No tests executed!
```

うーん？
テストが実行されません。

- [PHPUnit マニュアル – 第3章 コマンドラインのテストランナー](https://phpunit.de/manual/current/ja/textui.html#textui.examples.filter-patterns)

フィルタの文字列をくくる必要があるみたいですね。

```
$ composer test -- --filter 'Feature\\ExampleTest'
> phpunit '--filter' 'Feature\\ExampleTest'
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 710 ms, Memory: 12.00MB

OK (1 test, 1 assertion)
```

うまくいきました。

###コードカバレッジ
よくわかりませんが、書いてあるコマンドを叩いてみます。

    $ phpunit --coverage-html coverage

エラーが出ました。

    Error:         No code coverage driver is available

ぐぐります。

- [【手順】PHPのデバッグで便利なXdebugをMacに入れてみました | Mobile First Marketing Labo](http://www.aiship.jp/knowhow/archives/25695)

これで[紹介されていたサイト](https://xdebug.org/wizard.php)に、php -iの実行結果（めっちゃ長い）を貼り付けて、表示された手順に従ったらできました。

```
$ phpunit --coverage-html coverage
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

..                                                                  2 / 2 (100%)

Time: 2.28 seconds, Memory: 16.00MB

OK (2 tests, 2 assertions)

Generating code coverage report in HTML format ... done
```

HTMLファイルができているらしいけどどこにでしょう。

> カバレッジの結果はcoverage/フォルダ内にHTML形式で保存するようにします。

coverageフォルダを見てみるとなんかいろいろ追加されてました。
index.htmlを見ると、こんな感じ。

![スクリーンショット 2017-12-19 19.28.01.jpg](https://qiita-image-store.s3.amazonaws.com/0/214031/eb7226cb-7e9d-efa2-c808-6cf30241e9d8.jpeg)

おーすげえ。

##単体テストを作ってみる
- [Laravel5.5: 単体テストの例 - Qiita](https://qiita.com/sutara79/items/81cf687588c00df0f847)

最後の方の、

> (補足) テスト内でページを移動する方法

あたりが一切理解できていませんがスルーします。


##ブラウザテスト
- [Laravel5.5: ブラウザテストの基本 - Qiita](https://qiita.com/sutara79/items/95a5c59830006c715ae5)

うちの環境では以下の警告は表示されませんでした。

```
Warning: TTY mode is not supported on Windows platform.
```

あと、vagrant sshでduskを叩いてもブラウザ表示はできないみたいですね。
そりゃあ仮想環境側でブラウザ表示されますよね。
当たり前ですね（２０秒くらい気付かずに待ってしまった……）。

ローカルで起動したらちゃんとブラウザ起動できました。
速攻で閉じましたが。


##ブラウザテストの記述
###テスト用のDBの作成
もはやPHP関係ない！

> phpMyAdminでDBを新しく作ります。

とか書いてありますが完全に環境依存です本当にありがとうございました。

よくよく考えるとDB自体はHomesteadで作成された出来合いのものを利用しているので、中身がどうなっているのか知りません。
データベーススペシャリストの資格なんて、あってもこの程度のものですよ。
いや、違うんですよ。
あれ個々の製品にはフォーカスしないんですよ。

今度作ってみよう。
今回は面倒なのですっ飛ばします。

###ログインテストでエラー。
えらい怒られました。

```
$ php artisan dusk --filter LoginTest
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 2.19 seconds, Memory: 20.00MB

There was 1 error:

1) Tests\Browser\LoginTest::testLogin
Facebook\WebDriver\Exception\NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"body textarea[name='email']"}
  (Session info: headless chrome=62.0.3202.94)
  (Driver info: chromedriver=2.33.506092 (733a02544d189eeb751fe0d7ddca79a0ee28cce4),platform=Linux 4.4.0-101-generic x86_64)

/home/vagrant/code/Laravel/vendor/facebook/webdriver/lib/Exception/WebDriverException.php:102
/home/vagrant/code/Laravel/vendor/facebook/webdriver/lib/Remote/HttpCommandExecutor.php:320
/home/vagrant/code/Laravel/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:535
/home/vagrant/code/Laravel/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:175
/home/vagrant/code/Laravel/vendor/laravel/dusk/src/ElementResolver.php:332
/home/vagrant/code/Laravel/vendor/laravel/dusk/src/ElementResolver.php:310
/home/vagrant/code/Laravel/vendor/laravel/dusk/src/ElementResolver.php:88
/home/vagrant/code/Laravel/vendor/laravel/dusk/src/Concerns/InteractsWithElements.php:170
/home/vagrant/code/Laravel/tests/Browser/LoginTest.php:25
/home/vagrant/code/Laravel/vendor/laravel/dusk/src/TestCase.php:92
/home/vagrant/code/Laravel/tests/Browser/LoginTest.php:29

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
```

FEALUREじゃなくてERRORですね。
29行目ということはこの部分。

```
        $this->browse(function (Browser $browser) use ($user) {
            $browser->visit('/login') // ログインページへ移動
                    ->type('email', $user->email) // メールアドレスを入力
                    ->type('password', 'secret') // パスワードを入力
                    ->press('submit') // 送信ボタンをクリック
                    ->assertPathIs('/users/'.$user->id); // プロフィールページへ移動していることを確認
        });
```

……あー。
なんとなく/visitをフルパスにしてみたら動きました。

```php5
            $browser->visit('/login') // NG

            ↓

            $browser->visit('http://homestead.test/login') // OK
```

仮想環境からやったからですかね。
このあたりは資料の方でも微妙に動作が異なる部分として記載されているので、スルーします。

###CRUDのテストでエラー。
一応そのままの形態でテストを実施したところ、３件のテストすべてで同様のエラーが発生しました。

と思ってアドレスをフルパスに変えてみたのですが、動きませんでした。
面倒になったのでもうこの項目を全てスルーすることにします。


#というわけで完了。
長かった……。
途中、なぜかBootstrapの勉強とか挟むからいけないんだ。

正確には完了してませんが、最低限の『作りながら調べながら作る』の基礎はできました。
5.5の資料として、Laravelに初めて触れる人には必要十分な説明が記載されているので非常におすすめできます。