【初学者奮闘録】画像の保存／表示をする方法について（Laravel）

#はじめに
この記事は、独学開始から約３ヶ月の実務未経験者が作成したものです。
よって、スキルは非常に未熟なため、決して本記事の内容を鵜呑みにされないよう、ご注意ください。
（未熟な私が記事投稿を行なっている背景については、本文の最後にお伝えします。）

#本日の課題
自作のWebアプリ内で、【画像保存】と【画像表示】するための方法について、解説します。

###対象者
Laravelのインストールを完了している方
自作のアプリに、画像の保存／表示を実装したい方

###環境
PHP 8.0.11
Laravel Framework 8.64.0

###記事を読む前に頭に入れておいてほしいこと
【画像保存】は、DB内には保管せず、public（/storage）ディレクトリに保存していきます。
DBも使用いたしますが、それはあくまでも【パスを通すための文字列を保存する】ためです。
上記の内容を何となく頭に入れて、下記を読み進めてください。
（publicディレクトリは、appディレクトリやresourcesディレクトリ・routesディレクトリと同列に配置されています。）
（storageディレクトリはpublicディレクトリ直下にある、隠しディレクトリです。）

##public（/storage）ディレクトリにシンボリックリンクを立てる
ターミナルに以下のコードを入力してください。

```C#:ターミナル
php artisan storage:link
```

これで、public（/storage）ディレクトリに【シンボリックリンク】を立てることができました。
シンボリックリンクは、画像を表示するときに必要となります。
シンボリックリンクの意味については、下記の記事を参照ください。
https://wa3.i-3-i.info/word1151.html

##フォーム作成
画像を送信するためのフォームをHTMLで作成します。

```
  <form action="/store" method="POST" enctype="multipart/form-data">
  @csrf
    <div class="form-group">
      <label>画像を投稿する</label>
      <input type="file" name="img" class="form-control-file">
    </div>
    <button type="submit">投稿する</button>
  </form>
```

フォームを作成する上での注意点は以下の通りです。
●formタグには、必ず【enctype="multipart/form-data"】を挿入する
●inputタグには【type="file"】を挿入する

ここからは上記フォームで"心を燃やせ.jpeg"という名前をついた画像を送信したと仮定して話を進めます。
では、次の【画像を保存する】の説明に移りましょう。

##画像を保存する
"心を燃やせ.jpeg"という名前をついた画像を保存していきます。
まずはルーティングを用いて、App/Http/Controllers/GiftController.phpのstoreメソッドを呼び出します。

```#c:App/routes/web.php
Route::post('/store', "App\Http\Controllers\GiftController@store") ;

```

次にstoreメソッドで、【画像保存】をします。

```#c:App/Http/Controllers/GiftController.php
    public function store(Request $request){

//①画像をpublic（/storage）ディレクトリに保存する
　　　　　　　　　　　　　　　　　$img_pre = $request -> img;
        　$filename = $img_pre -> getClientOriginalName();
        $img_post = $img_pre　->　storeAs('public',$filename);

//②画像の文字列をDBに保管する
        $gift = new Gift;
        $gift ->img = $img_post ;
        $gift -> save();

        return redirect("/"); 
    }
```

###①画像をpublic（/storage）ディレクトリに保存する
①のプログラムでは、画像をpublic（/storage）ディレクトリに保存します。

１行目で、フォームで送られてきた画像（＄request->img）を＄img_preに代入します。

2行目のgetClientOriginalName()ですが、これは『保存する画像の名前を決めるための関数』です。
このgetClientOriginalName()により、保存される画像は、"心を燃やせ.jpeg"の名前のままに保存することができます。
もしgetClientOriginalName()を使用しなければ、パソコン側で意味不明な名前を勝手に命名してしまいます。
getClientOriginalName()で命名した文字列を＄filenameに代入します。

３列目で、いよいよ画像本体を保存していきます。
それにはstoreAs関数を使用します。
storeAs関数は第３引数まで設定することができます。
●第１引数・・・パス名（ここは空白で問題なし。むしろ、文字列が乱れてパスが通らなくなるため、注意が必要。）
●第２引数・・・画像を保存する時の名前指定（ここは＄filenameで定義した名前で保存）
●第３引数・・・画像を保存する場所を指定（今回は'public'を指定）

これで、public（/storage）ディレクトリに画像が保存されました。

###②画像の文字列をDBに保管する
②のコードでは、DBに文字列を保存します。
今回の場合、"心を燃やせ.jpeg"という文字列のみが、DBに保存されます。
これにより、public（/storage）ディレクトリに保存された画像を取り出すためのパスを保存したこととなります。


##画像を表示する
いよいよ画像を表示します。

```#c:resources/views/show.blade.php
<img src=" {{ asset('storage/'.$gift　->　img) }}">
```

asset（)関数は、publicディレクトリのパスを通すための関数です。
まず、最初にシンボリックリンクを通しているpublicディレクトリの隠しディレクトリであるstorageディレクトリを宣言します。
そして、DBに保存した"心を燃やせ.jpeg"という文字列を、＄gift　->　imgで取り出します。
これでパソコンに対し、「パソコンさーん、public/storageディレクトリにある"心を燃やせ.jpeg"）を表示させてください！」と指示できます。
結果、パソコンさんは"心を燃やせ.jpeg"の画像を画面に表示されるということです。

#最後に
上記でもお伝えいたしましたが、私は独学開始から約３ヶ月の実務未経験者です。
そんな未熟な私が記事を投稿しようと決意した理由は、以下の通りです。
・初学者の記事が多く出回るほどに、プログラミングの学習を検討している方の背中を押せると考えたから（私自身、学習を開始するまでに初学者の記事を読み漁っておりました）
・周りに同じ境遇の仲間がいない、孤独な初学者さんの競争心を掻き立てられるのではと考えたから（学習効率を上げるためにはライバルの存在は重要）
・あるいはこのような稚拙な記事を読んだ初学者さんが「自分のレベルはこいつよりも上」と優越感を与えられるのではと考えたから（学習効率を上げるためには自信を持つことも重要）

プロのエンジニア同様、初学者にもそれなりの努めがあると、私は思います。
今後も、下手くそながらも【初学者ページ】を上げ続けて参ります。

最後まで読んでいただき、誠にありがとうございました。