Open16

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
  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
ログインするとコメントできます