shigechi-64's diary

自由・自主・自立・自尊

LaravelでHerokuにデプロイ後、謎のエラーに苦しんだ話

結論

Laravelで作ったアプリケーションは/vendor以下がデフォルトで.gitignoreに含まれている為、gitリポジトリに変更が反映されない。
従って、/vendor下のファイルに修正を加えた場合、シンプルにHerokuにデプロイしただけではHerokuアプリにはその変更は反映されていない。
Heroku側で直接そのファイルを修正する方法を模索したがうまくいかなかった為、結局/vendor以下を.gitignoreから外してリポジトリに含めるようにしたところ、エラーが解消されたという話。

そもそもの問題

ログインページだけ作ってとりあえずHerokuにデプロイして動作確認をしようとしたら、

The email field is required.

と言われる。どうもpostLogin時のバリデーションで引っかかっているみたいだけど開発環境では問題なし。むむむ。

DBを開発環境と合わせてみた

特に何の根拠もなく開発環境と本番でDBが違うのがだめなんか?と思ってHeroku側で使うDBをPostgreSQLからMySQLに変更してみた(Herokuアプリの作成からやり直した)。本当に何の根拠もなかったけど違うとこってそこしかないやろーとこのときは思っていました。この過程で「開発・本番等価」という考え方を知る。エラーが解消するかどうかは別にして、開発と本番でDBを同じにしてバチはあたるまい。

sizukutamago.hatenablog.com

ま、結果エラー解消しなかったんですが。がびーん。

postLogin時の流れを深掘り

最初からこれをやれば良かったんですが、ログイン処理中のどこでこのエラーが吐かれるのかを追跡してみる。まずはルーティングから。

routes.php

// ログイン認証
Route::get('login', 'Auth\AuthController@getLogin')->name('login.get');
Route::post('login', 'Auth\AuthController@postLogin')->name('login.post');
Route::get('logout', 'Auth\AuthController@getLogout')->name('logout.get');

AuthControllerのpostLoginアクションに飛びます。でもpostLoginアクションの実体はAuthControllerにはなく、
/vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php
に含まれているようだ。

/vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php

・
・
public function postLogin(Request $request)
{
        $this->validate($request, [
            $this->loginUsername() => 'required', 'password' => 'required',
        ]);
・
・

ここだなーここは怪しいです。passwordがrequiredなのはいい。loginUsername()っていうのが超あやしい。なぜかというと今回、Laravelの標準で用意されているusersテーブルのマイグレーションファイルをそのまま使ってはいないからです。具体的にいうと標準だと「email」になっているカラムのカラム名を「member_id」に変更しているのです。なんかその辺が原因なんじゃないかなーと思いつつ同じファイル内にあるloginUsername()を見てみる。

・
・
public function loginUsername()
{
        return property_exists($this, 'username') ? $this->username : 'email';
}
・
・

んーこれくさいです。この関数はその名の通りユーザ名を返すのだろうけど、最初に設定されているのが「email」なのだな。でもそんなカラム名はないので前掲のエラーとなって現れるということのような気がする。ということはここを「member_id」に変えてやればうまくいきそう。でもこれ開発時に既にぶちあたった問題で、ちゃんと直したはずなんだけど・・・

/vendor以下は無視される

ローカルリポジトリではエラーが出ないので、リモートではどうなっているのかと思いGithubでソースを確認しようとしたところ・・・/vendorディレクトリが存在しない!どうやらLaravelではデフォルトで/vendorディレクトリが.gitignoreに含まれており、リポジトリには含まれないようになっているみたい。よくわからんが環境ごとに用意してねってことらしい。

qiita.com

Heroku側で直接ファイル編集したらよくね?

リポジトリには含まれていないけど、Heroku側にも必ずこのファイルはあるはずなので、じゃあそれを直接修正したらよさそうねってことでheroku run bashして/vendor/laravel/framework/src/Illuminate/Foundation/Authに移動。んでAuthenticatesUsers.phpvimかなんかで編集っと・・・あれれvimがない?てか何で編集したらいいの?vi?nano?わかりません。いろいろ調べてみたけどよくわからず、同じように悩んでいる人はStackOverflowで見つけた。

stackoverflow.com

なんかheroku-vimっていうプラグインを入れればvimが使えるようになるっぽいけどどうもうまく入れられない。↑でもそういう人いますね。んーどうしようと思ってたら同じ記事に以下の回答が・・・

gyazo.com

ほほーなんかすごい回りくどいけど確かにこの方法でもできそう。よし、やってみよう!てことでGistにAuthenticatesUsers.phpを登録して該当箇所を修正、Heroku側からwgetでファイルを取得。できた!なんかもっと簡単な方法絶対あると思うけどとりあえずこれでいってみよう!と満足してこの日は作業終了した。

編集がリセットされる??

よーし、これで大丈夫なはずだぞーと思って再度動作確認。・・・あれ、直ってないけど・・・なんで?もう一度/vendor/laravel/framework/src/Illuminate/Foundation/Authに移動してファイルのタイムスタンプを確認してみると、修正していないファイルと同じタイムスタンプになっている。なんでやー!調べてみるとどうもHerokuではgitを経由しないファイルの書き換えはリセットされてしまうそう。どこで見た情報かは忘れました。

/vendor以下もリポジトリに含めてしまおう

なんかお作法的にはだめっぽいけどもういいやと思って/vendor以下もリポジトリに含めることにしました。結果無事修正が反映されてエラーは出なくなりました。デフォルトのUsersマイグレーションをいじらなければ/vendor以下を修正する必要もなかったかもと思ったけど、これからたぶんいじらないといけない場面も出てくると思うんだよなー。どうするのが正しかったんだろう・・・よくわかりませんがとりあえず今の自分にできるのはこれが精一杯でした。あまり時間もかけていられないのでとりあえずこの方法で行きたいと思います。こういう純粋なプログラミング以外のことではまるのってけっこうストレスですけどひとつひとつ解決していくしかないですね。それでは今日はこのへんで。