プロフィール登録や編集で画像ファイルの登録機能って必須ですよね。
例えば、実際に僕が作ったものですが、こんな感じのものです。
名前やメールアドレスだけでなく、プロフィール画像を設定できるようになっています。
今回はこの「画像をアップロードする機能」をLaraveでどうやって実装するのかについて解説していきます。
具体的には画像ファイルのバリデーションを行う方法や、ファイルの保存先の設定方法などです。
やり方がわからないという人はぜひ参考にしてみてください。
画像ファイルアッロード機能の実装手順
まずは、View側の書き方について紹介し、それからController側のバリデーションについて解説します。
1. ファイルを送信するための記述(View)
見やすくするために、クラス名などは省略してしますが、次のように書きます。
<form action="{{route('prof.edit')}}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="pic">
<input type="text" name="name">
<input type="email" name="email">
<input type="submit" value="登録する" >
</form>
ファイルを送信するときは、formに「enctype=”multipart/form-data”」の記述を忘れないように注意しましょう。
また、inputのtype属性には「file」を指定します。
これで画像ファイルが送信できるようになります。
2. Controller側の記述
続いて、Viewから送られてきたファイルをコントローラー側でバリデーションを行い、保存する方法です。
今回は「画像アップロード機能の実装方法」の解説なので、こちらもをわかりやすくするために、細かい処理(分岐)は省力しています。
public function prof(Request $request){
// バリデーション
$request->validate([
'pic' => 'file|image|mimes:jpeg,png,jpg|max:2048', //画像ファイルのバリデーション
'name' => 'required|string|max:255|unique:users,name',
'email' => 'required|string|max:255|email|unique:users,email'
]);
//ログインしているユーザーの情報を取得
$user = Auth::user();
//画像ファイルのパス
$img_url = $request->pic->storeAs('public/upload', Auth::id() . '.jpg');
//DB更新処理
$user->name = $request->name;
$user->email = $request->email;
$user->pic = str_replace('public/', 'storage/', $img_url);
$user->save();
// マイページへリダイレクト
return redirect('/mypage')->with('flash_message', 'プロフィールを更新しました');
}
1. 画像ファイルのバリデーション
まず、バリデーションのルールですが、次のように書きます。
'pic' => 'file|image|mimes:jpeg,png,jpg|max:2048'
こうすることで、POST送信されたファイルが画像かどうか、MIMEタイプが指定されたものかどうか、ファイルのサイズは制限内であるかどうかなどをLaravel側で自動判定してくれます。
2. ファイルの保存
バリデーションが終わると、DBの更新処理に移りますが、その前に画像をサーバー上に保管します。
その処理が以下です。
$img_url = $request->pic->storeAs('public/upload', Auth::id() . '.jpg');
storeAsを使うことで、第一引数に指定したパスに、第二引数に指定した名前でファイルを保存され、$img_urlには画像ファイルのパスが格納されます。
上記の例でいくと、「public/upload」の中に、「ログインユーザーID.jpg」でファイルを保存することになります。
しかし、実際には画像は「public/upload」に保存されず、「storage/app/public/upload」に保存されます。
これは、Laravelが「storage/app/public」配下にファイルを置いて、「public/storage」から「storage/app/public」にシンボリックリンクを貼ってアクセスすることを推奨しているためです。
何言ってるか全然わからんぞ・・・。シンボリックリンクって何やねん。
と思った方。
シンボリックリンクとは、簡単に言えばWindowのショートカット機能みたいなものだと思ってください。
下の画像のように「public/storage」というショートカットを作っておき、そのショートカットにアクセスすると、「storage/app/public」にジャンプするようにリンクを貼ります。
要は、実際の画像は「storage/app/public」配下に保管しておいて、画像を読み込む時は「public/storage」からジャンプして読み込みましょうって話です。
なので、今回の例でいくと、画像を読み込むには「public/storage/upload」にアクセスする必要があるので、DBにパスを登録するときに$img_urlのパスを少し変換し登録します(後述)。
話がややこしくなってきましたが、まずは「public/storage」から「storage/app/public」へのシンボリックリンクを貼りましょう。
貼り方はターミナル上で以下のコマンドを実行します。
php artisan storage:link
3. DB更新
最後にDBの更新です。
サンプルコードの以下の項目でDBを更新しています。
//DB更新処理
$user->name = $request->name;
$user->email = $request->email;
$user->pic = str_replace('public/', 'storage/', $img_url); //画像パスの格納
$user->save();
$user->picには画像のファイルパスが格納されますが、$img_urlには「public/upload/ファイル名」が格納されているので、このままだとView側で画像を読み込むことができません。
そのため「public/storage/upload/ファイル名」に変更する必要がありますが、View側で画像を読み込む場合は「public」は要らないので、「storage/upload/ファイル名」に変換すればOKです。
つまり「public」を「storage」に変換すればOKなので、str_replace関数を使っています。
これでDBのpicカラムには「storage/upload/ファイル名」で登録されます。
3. 登録した画像の表示(View)
先ほどのViewにimgタグを追加して表示します。
<form action="{{route('prof.edit')}}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="pic">
<img src="/{{ $user->pic }}" > //追加
<input type="text" name="name">
<input type="email" name="email">
<input type="submit" value="登録する" >
</form>
これで、登録した画像をViewで読み込んだり、アップロードすることができます。
クラスの設定や、細かい処理の制御は書いていないので、あとはあなたが作っているサービスに合わせて付け加えてください。
また内容に間違いがあれば、指摘いただけると幸いです。
おすすめのLaravelの書籍
(2024/11/21 11:12:15時点 Amazon調べ-詳細)