Webアプリケーションをリリースするには、デプロイという操作が必要になります。
しかし、デプロイしたWebアプリケーションですが、ローカル環境では、動くのにデプロイすると動かないという問題が発生し、解決するのに時間を要した話を紹介します。
事の経緯
デプロイした側では、ある操作をすると画面が真っ白になり、ログなどで確認しても、一切エラーメッセージが出ませんでした。これが、解決するのに更に時間を要した原因でもあります。
ある操作とは、ボタンをクリックすると、該当記事に関する情報を保存するというよくある内容です。
クリックすると
マイページに登録される
しかし、デプロイした側では、クリックすると
真っ白に… _| ̄|○
マイページで確認しても、記事が登録できていませんでした。
本記事のWebアプリケーションの開発環境は、
OS:CentOS、フレームワーク:Laravel6.20、プログラミング言語:PHP7です。
ソースコード
blade.php(一部)
<form action="/store" method="POST">
@csrf
<input type="hidden"name="news[name]" value="<?php echo $id;?>">
<input type="hidden"name="news[title]" value="{{ $data['name'] }}">
<input type="hidden"name="news[url]" value="{{ $data['url'] }}">
<input type="submit" value="favorite">
</form>
Controller.php(一部)
public function store(News $favorite, Request $request)
{
$post = News::all();
$counts = $post->count();
$id=Auth::id();
$url = $request->news['url'];
for ($i = 0;$i<$counts; $i++){
if ($post[$i]['name'] == $id && $post[$i]['url'] != $url){
if ( $i == $counts-1 ){
$input=$request["news"];
$favorite->fill($input)->save();
session()->flash('msg_success', '登録しました');
return redirect()->back();
}
}elseif($post[$i]['name'] == $id && $post[$i]['url'] == $url){
session()->flash('msg_danger', 'すでに登録済みです');
return redirect()->back();
}
elseif($post[$i]['name'] != $id && $i==$counts-1 ){
$input=$request["news"];
$favorite->fill($input)->save();
session()->flash('msg_success', '登録しました');
return redirect()->back();
}
}
}
web.php(一部)
Route::post("/store","NewsController@store");
migration(一部)
class CreateNewsTable extends Migration
{
public function up()
{
Schema::create('news', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('title');
$table->string('url');
//$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('news');
}
}
データベースなどを確認するも異常なしです。
原因
一見、なにも問題はなさそうですが、決定的な問題があります。
実は、ローカルで動いて、デプロイしたら動かないというのは、間違っていて、ローカルでも動かないことがわかりました。
Controllerで、データベースにアクセスして、post変数に代入しています。
$post = News::all();
その後、テーブルnewsのidやらurlなどを比較する流れになるのですが、まず大前提として、テーブルにデータが入っているという条件の下で処理をしていました。
ですので、migrationをrefreshすると画面が真っ白になるというデプロイしたときと同じ状況に陥りました。
解決法
以下のように、もしデータがない(一番初め)の場合も考慮に入れることで解決いたしました。
Controller.php
public function store(News $favorite, Request $request)
{
$post = News::all();
$counts = $post->count();
$id=Auth::id();
$url = $request->news['url'];
//追加
if($counts==0){
$input=$request["news"];
$favorite->fill($input)->save();
session()->flash('msg_success', '登録しました');
return redirect()->back();
}
//
for ($i = 0;$i<$counts; $i++){
if ($post[$i]['name'] == $id && $post[$i]['url'] != $url){
if ( $i == $counts-1 ){
$input=$request["news"];
$favorite->fill($input)->save();
session()->flash('msg_success', '登録しました');
return redirect()->back();
}
}elseif($post[$i]['name'] == $id && $post[$i]['url'] == $url){
session()->flash('msg_danger', 'すでに登録済みです');
return redirect()->back();
}
elseif($post[$i]['name'] != $id && $i==$counts-1 ){
$input=$request["news"];
$favorite->fill($input)->save();
session()->flash('msg_success', '登録しました');
return redirect()->back();
}
}
}
まとめ
この問題の当初は、ローカルで動くのにデプロイしたら動かないと勘違いし、かつエラーメッセージが表示されないので、非常に解決まで時間がかかりました。
ローカルで動くのにデプロイしたら動かないと思ったとき、ローカルでもmigrationをrefreshして、データをまっさらにすることでherokuと同じ環境にして確認することが肝でした。
両者で環境下が違う場合、同じ環境下にすることで、再度考えることがとても大事であると痛感させられました。