【Laravel基礎】フォームからの画像保存と表示方法【シンボリックリンク】

#概要#
Laravel学習で自分がつまずいた部分を備忘録としてまとめています。
今回はフォームからの画像保存と表示方法に関する記事です。

#つまずいたポイント#
食べログ風のアプリを作成しようとした所、投稿の画像表示につまづきました。
具体的には、
①画像をstorage/app/publicに保存
②storage/app/publicに保存した画像の表示
に苦戦しました。。

苦戦の末、下記の手順で解決出来たので記事にしてみました。
####①画像をstorage/app/publicに保存####
####②シンボリックリンクを作成####
####③assetヘルパを用いて表示####

書いて見ると非常にシンプルですね。。
以下、記事内容です！

#画像の保存#
画像の保存と画像の表示は切り分けて考えます。

保存方法から記述していきます。
まずテーブルと追加用フォームを用意。

```laravel:imagesテーブル
      public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->increments('id');
            $table->string('shop_name');
            $table->string('path');
            $table->string('spot');
            $table->timestamps();
        });
    }
　　
```

今回は`pathカラムに画像名を代入し、それをビューで表示します。`

フォームはこんな感じ。
![スクリーンショット 2020-12-08 19.09.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/839989/47ed014a-729c-1037-0e3e-7da8c0423b21.png)


###■コントローラ###
フォームから飛んだ画像データを、コントローラで保存します。

```laravel:ImageController
     public function add(Request $request){
　　　　　　　①画像データを変数$pathに代入＋storage/app/publicに保存
            $path = $request->path->store('public');
            
　　　　　　　②変数$imageのpathカラムに$pathのbasenameを代入
            $image = [
            'shop_name' => $request->shop_name,
            'spot'  => $request->spot,
            'path'  => basename($path)
            ];
            \DB::table('images')->insert($image);

            $images = \App\Image::all();
            return view('user.home',compact('images'));
    }
```

①Requestから受け取った画像データを変数pathに代入。同時に,storeメソッドを使って保存します。`画像の保存先`ですが、`storage/app/public` 内に保存します。`storeメソッドの引数には('public')`を指定します。

②変数imageを作成。`pathカラム`に、画像データの`basename`と言う値を代入して保存。テーブルに追加してビューに渡します。

上記がフォームから来た画像の保存処理です。`画像データをstorage/app/publicに保存`。そして`画像のbasenameを投稿の'path'カラムに代入`しました。後述しますが`ビュー上で、このbasenameを参照して画像を表示`させます。

###失敗例###
storeメソッドを用いた保存について、自分の失敗例を挙げておきます。

```laravel:ImageController
     public function add(Request $request){
　　　　　　　
            $path = $request->path->store('storage/app/public');
            
    }
```

`storage/app/public`に画像を保存したいために、storeメソッドの引数に('storage/app/public')を設定していました。
結果は下記の通りです。
![スクリーンショット 2020-12-08 19.45.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/839989/240a200e-f578-50cd-8591-531d3464e0a1.png)
`storage/appの下に、更にstorage/app/publicが出来ています。`
これは、`storeメソッドのデフォルト名前空間が('storage/app')`になっているために起きた失敗でした。デフォルトの('storage/app')の下に、更に('storage/app/public')が追加された感じですね。
なので, storeメソッドを用いて`storage/app/public`に保存したい場合, 引数を`store('public')`とします。


次に保存した画像の表示方法です。


#画像の表示(シンボリックリンク)#
先ほど`storage/app/public`に保存した画像をビュー上で表示していきます。
ただし、`storageフォルダに保存した画像には直接アクセス出来ません。`Laravelで作ったアプリケーションが公開されるとき、`アクセス出来るフォルダはpublicフォルダの中身のみ`だからです。
そこで登場するのが`シンボリックリンク`です。
下記コマンドで実行します。

```laravel:ターミナル
    php artisan storage:link
```

これにより、publicの中にstorageフォルダが生成されます。(シンボリックリンク)
これは、storageフォルダへのショートカットキーのようなものです。
`storage/app/public`内に画像が保存されたら、このシンボリックリンクの中身にも反映されます。publicフォルダの中にあるので、アクセス可能と言う訳ですね。
このシンボリックリンクを用いて、ビュー上で画像を表示していきます。
![スクリーンショット 2020-12-09 13.41.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/839989/f5c21360-65de-f071-edaa-c66ed091a661.png)

後はビュー上でassetヘルパを使い、シンボリックリンク内の画像を表示します。
assetヘルパを使う事でpublicフォルダ内にアクセス出来ます。

```laravel:
<img src="{{ asset( 'storage/'.$image->path )}}"　>
```           

【表示結果】
![スクリーンショット 2020-12-09 14.00.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/839989/cb96f7cd-5d20-d24e-6225-939d012cd6bc.png)

こうですね。無事に画像表示出来ました。


##まとめ##
以上、Laravelにおけるフォームからの画像保存と表示でした。
①storeメソッドを用いてstorage/app/pulicに画像保存
②publicフォルダ内にシンボリックリンクを生成
③assetヘルパを用いて画像表示。
という流れですね。

最後まで読んで頂きありがとうございました！