LoginSignup
1
3

More than 1 year has passed since last update.

Laravelで画像をアップロードする方法

Last updated at Posted at 2022-09-06

Laravelで画像をアップロードするフォームを作成する

著者の環境

著者は事前にCRUD用のコントローラを作成しており、ルーティングが次の状態にしてます
ルーティングの内容が異なる場合はご自身の環境に合うようURIを変える必要があります
CRUD用コントローラの役割

Route::resource('/', '******Controller');

php artisan route:list

+--------+-----------+----------+---------+--------------------------------------------------+--------------+
| Domain | Method    | URI      | Name    | Action                                           | Middleware   |
+--------+-----------+----------+---------+--------------------------------------------------+--------------+
|        | GET|HEAD  | /        | index   | App\Http\Controllers\******Controller@index   | web          |
|        | POST      | /        | store   | App\Http\Controllers\******Controller@store   | web          |
|        | GET|HEAD  | api/user |         | Closure                                          | api,auth:api |
|        | GET|HEAD  | create   | create  | App\Http\Controllers\******Controller@create  | web          |
|        | GET|HEAD  | {}       | show    | App\Http\Controllers\******Controller@show    | web          |
|        | PUT|PATCH | {}       | update  | App\Http\Controllers\******Controller@update  | web          |
|        | DELETE    | {}       | destroy | App\Http\Controllers\******Controller@destroy | web          |
|        | GET|HEAD  | {}/edit  | edit    | App\Http\Controllers\******Controller@edit    | web          |
+--------+-----------+----------+---------+--------------------------------------------------+--------------+

ビューにファイルをアップロードするフォームを作成する

  • ビューにフォームを用意しコントローラーへ画像を送ります
<form method="POST" action="/" enctype="multipart/form-data">
  @csrf
  <input type="file" name="image">
  <button>アップロード</button>
</form>

用語説明

method="POST"

  • ブラウザの<form>に入力された情報を特定のURI(コントローラーのアクション)へ送ります

action="/"

  • <form>を送信する先を"/"へ指定しています。
  • methodをPOSTにすることで移動先はindexアクションではなくstoreアクションになります

enctype="multipart/form-data"

  • フォームで画像をアップロードする際に必須レベルで記述しなければならない項目
  • HTMLフォームのHTTP通信で複数の種類のデータを一度に扱える形式
  • 記述がない場合サーバーサイド側が適切にデータを受け取れない可能性がある

@csrf

  • CSRF(クロスサイトリクエストフォージェリ) による脆弱性を防止するための記述です
  • Laravelでフォームを利用する際には必ず記述しなければならないコードになります
  • Laravelでは<form>の内部に@csrfを記述しなければ脆弱性対策でエラーを起こします
  • @csrfとは同じ意味の{{csrf_field()}}を記述しても<form>は動きます

type="file"

  • ブラウザに表示されるボタンを押すことでファイルを選択することができるようになります

name="任意の名前"

  • フォームで送るデータに名前を付けます
  • コントローラーに渡されたデータは任意の名前を引数にすることで参照することができます
  • 渡されるデータはファイル名,画像データ,作成日時など様々な項目がセットになっています
  • コントローラーで利用する際にはfile関数やstoreAsメソッドの引数に使います

<button>

  • ボタンを押すことでフォームのデータを送信することができます

コントローラーで画像を保存する(ファイル名ランダム)

  • 画像データはLaravelのプロジェクトフォルダへ保存されます
  • データベースへファイル名や保存先のパスなどを保存すればビューへ画像を呼び出すことができます
  • CRUD用のコントローラーを用いているためstoreアクションにコードを記述しています
public function store(Request $request)
    {
        // ディレクトリ名を任意の名前で設定します
        $dir = 'img';

        // imgディレクトリを作成し画像を保存
        // storage/app/public/任意のディレクトリ名/
        $request->file('inputタグに付けられたname属性の値')->store('public/' . $dir);
        
        // ページを更新します
        return redirect('/');
    }
  • storeメソッドの引数には保存先のディレクトリ名を指定することができます。
  • ファイルはランダムな一意の値(アルファベット+数字)にリネームされて保存されます

画像を保存する(ファイル名を変更せずに保存する)

  • storeAsメソッドを使用することでファイル名を指定して保存することができます
 public function upload(Request $request)
    {
        // ディレクトリ名
        $dir = 'img';

        // アップロードされたファイル名を取得
        $file_name = $request->file('inputタグに付けられたname属性の値')->getClientOriginalName();

        // 取得したファイル名で保存
        // storage/app/public/任意のディレクトリ名/
        $request->file('inputタグに付けられたname属性の値')->storeAs('public/' . $dir, $file_name);

        return redirect('/');
    }
  • phpの変数はドット.で連続した表示をすることができます
  • $maxUserId = Products::max('id')+1;では次のレコードのIDを変数に代入することができます

画像の保存先パスをデータベースに保存する

  • 事前にデータベースのテーブルを操作するためのモデルを作成する必要があります
  • 作成したモデルを任意の変数に入れることでデータベースを操作するインスタンスを作成します
  • 作成された変数(インスタンス)に挿入先の列を指定することで値を代入することができます
$image = new User();
// $任意の変数名 = テーブルを操作するモデル名();
// storage/app/public/任意のディレクトリ名/
        $image->file_name = $file_name;
        $image->file_path = 'storage/app/public/' . $dir . '/' . $file_name;
        $image->save();
   
   //ページを更新する 
   return redirect('/');
 
$image->実際に存在するテーブルの列名 = $file_name;
$image->実際に存在するテーブルの列名 = 'storage/app/public/' . $dir . '/' . $file_name;
  • $変数名->saveでデータベースに1レコードが登録されます
  • saveを動かす場合、1レコードに存在する列(カラム)は一度に全て値を埋める必要があります
  • saveを動かす場合、レコードの値に1つでも空欄がある場合、エラーになります
  • file_nameやfile_pathの列以外にも列が存在する場合は、それら全て値で埋める必要があります
  • 自動で入力されるIDや更新日時(created_at)などは埋める必要はありません

ビュー表示への下準備(シンボリックリンク設定)

  • Laravelでは画像の参照先はstorage/app/public/です
  • ただし、そのままではビューで参照することができません
  • storageディレクトリを参照するためにはシンボリックリンクが必要です

Laravelではシンボリックリンクが必須

  • windowsで言うところショートカットの意味
  • Laravelはデフォルトでstrageはweb側から参照できない仕様です
  • Laravelでstrageを参照する場合はシンボリックリンクを貼りましょう

シンボリックリンクを作成するコマンド

  • storageへのシンボリックリンクが作成されます
  • ブラウザから参照可能になります
php artisan storage:link

ビューに画像を表示させるコード

  • braidファイルへ次のコードを記述することで画像を参照できます
  • コントローラーからモデルが代入された変数を渡しておく必要があります

@foreach($users as $user)

<img src="{{ asset($user->img_path) }}" >

@endforeach


@foreach($コントローラから渡した変数名 as $任意の変数名)

<img src="{{ asset($任意の変数名->パスが格納された列名) }}" >

@endforeach

asset関数とは?

  • publicディレクトリのパスを返す関数です
  • 使用することでpublicまでのパスを省略することができます

実際のテーブルに入力をしておくべきパス

  • storage/ファイル名.jpg
  • storage/任意のフォルダ名/ファイル名.jpg
  • asset関数の引数に入力することで画像ファイルを参照します
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3