Edited at

[Laravel] ユーザーのアイコン画像を投稿、表示させる機能の実装したのでメモ(画像の保存場所は?シンボリックリンクって?)

More than 1 year has passed since last update.


やりたいこと

Laravel で勉強のために簡単な CRUD アプリを作成中です。

ユーザーが自分のアイコン画像を投稿できる機能を実装しました。

ためになった知識や注意点などを自分用に備忘録としてメモします。

キャプチャ.PNG

こんな感じのイメージです。


画像はどのディレクトリに保存すればいいの?

コントローラーで受け取った画像などのファイルですが、基本的に storage/app/public 内に保存するようです。

(ただし、public ディレクトリに入っているファイルは誰でもアクセスできてしまうため、公開したくないファイルの場合は別途処理が必要みたいです。)


UserController.php

public function image(Request $request, User $user) {

// バリデーション省略
$originalImg = $request->user_image;

if($originalImg->isValid()) {
$filePath = $originalImg->store('public');
$user->image = str_replace('public/', '', $filePath);
$user->save();
return redirect("/user/{$user->id}")->with('user', $user);

}


上記コントローラーでは <input type="file" name="user_image"> で送った画像ファイル $request->user_imagestore('public') とすることで public ディレクトリに保存してます。

config 内の filesystems.php を確認するとディスクの設定が確認できます。初期設定では storage/app ディレクトリに保存されるようになっているので、public ディレクトリに保存するために store メソッドの引数にディレクトリ名 public を指定します。

また、どの画像がどのユーザーのアイコンなのかを識別するために、ファイル名をユーザーテーブルに保存しています。store メソッドの戻り値としてファイルのパスが渡されるため、そのパスをユーザーテーブルの image カラムに保存します。その際、パス名が public/xxxxxxxxxx.jpg となるので不要な public/ の部分を削除しています。


シンボリックリンクって?

Laravel で作ったアプリケーションが公開されるとき、公開されるのは一番上の階層にある public ディレクトリのみです。public ディレクトリにファイルや処理のすべてが集約されています。なので、保存した画像も public ディレクトリ内に存在しないとアクセスすることができません。そこでシンボリックリンクを利用して storage ディレクトリにアクセスできるようにします。

キャプチャ.PNG

今回初めてシンボリックリンクとうい単語を知りました。

といっても特に難しいものではなく、UNIX 系で使われるいわゆるショートカットのようなもののようです(厳密には違いがあるのかもしれませんが...)。

シンボリックリンクは Artisan コマンドで作成できます。

php artisan storage:link

キャプチャ.PNG

これで storege へのリンクができたので画像データへアクセスできます!

右側にちょこんとくっついてる矢印がリンクのマークかと思われます(画像はVSCode)。


画像が表示されるか試してみる

作成したシンボリックリンクの中を見てみると、当然ですが storage/app/public の中身がこんにちわしてます。以下のようにビューを編集すれば画像が表示させるはず!

@if($user->image == null)

<img src="/storage/noimage.png">
@else
<img src="/storage/{{$user->image}}">
@endif

ユーザーアイコンがなければ noimage.png を表示、アイコンが登録されていればユーザーテーブルの image カラムからファイル名を引っ張ってきます。

<img> タグの src= につづくパス名は、一番上の階層の public ディレクトリがルートディレクトリになりますので、"/storage/xxxxxxxxx.jpg" などとすることで画像へアクセスすることができます。この storage はシンボリックリンクのことですね。

キャプチャ.PNG

よし!成功~

今回は以上です。