初めてのLaravel ⑩。画像をアップロードしよう

初めてのLaravel ⑩。画像をアップロードしよう
この記事はこんな悩みを解決します
  • 画像のアップロードの仕方が知りたい
  • 画像を保存して取り出せるようにしたい
  • Laravelについて勉強したい

ブログだったり、SNSだったりとWebアプリの中で画像をアップロードして使いたいという場合がると思います。文字で書くよりも効率的に情報が伝わるので画像を扱えるようになるとユーザーに喜ばれます。

この記事を読む事でLaravelでの画像のアップロードの方法が分かります。

初めてのLaravel ⑩。画像をアップロードしよう

今回は画像を選択してサーバーに保存して行く方法を紹介します。まずは画像をアップロードする方法を確認しましょう。

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

画像をアップロードするにはformを使って行きます。

<form action="{{ url('/upload', $user->id) }}" method="POST" enctype="multipart/form-data">
		@csrf
	    <!-- アップロードした画像。なければ表示しない -->
	    @isset ($filename)
	    <div>
	        <img src="{{ asset('storage/' . $filename) }}">
	    </div>
	    @endisset
	    <!-- エラーがあれば表示する -->
	    @if ($errors->any())
		 <div class="alert alert-danger">
		    <ul>
		    @foreach ($errors->all() as $error)
		        <li>{{ $error }}</li>
		    @endforeach
		    </ul>
		 </div>
		 @endif

	    <label for="photo">画像ファイル:</label>
	    <input type="file" class="form-control" name="picture">
	    <input type="submit" value="Submit">
	</form>
画像をアップロードする時のポイント
  • formの属性にenctype=”multipart/form-data”を記入し、ファイルを認識するようにする
  • inputの属性にtype=”file”を記入し、ファイルをアップロードできるようにする
  • @issetでファイルがあれば表示する仕組みにする
  • @ifでエラーがあれば表示する仕組みにする

保存した画像ファイルを呼び出すときには@issetを変えて行きますが、とりあえずアップロードしたファイルが呼び出せるように設定して行きます。

web.phpの設定

/uploadにアクセスするように書いたのでweb.phpを編集して行きます。

Route::post('/upload/{id}', 'PictureController@store');

では、PictureControllerを作って編集して行きます。
まずはTerminalでPictureControllerを作成します。

コントローラーの設定

mbp:training user$ php artisan make:controller PictureController
Controller created successfully.

うまくいったのでPictureControllerを編集して行きます。

public function store($id, Request $request){
      $this->validate($request, [
            'picture' => 'required|file|image|mimes:jpeg,png,jpg,gif|max:1148'
            ]);
    	if ($request->file('picture')->isValid([])) {
            $path = $request->file('picture')->store('public');
            $user = User::find($id);
            return view('comment')->with([
            	'filename' => basename($path),
            	'user' => $user,
            ]);
        } else {
            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['file' => '画像がアップロードされていないか不正なデータです。']);
        }
    }
画像ファイルをアップロードする時のポイント
  • バリデーションを行い、アップロードされたファイルが画像か確認します。
  • ifの条件ではfileメソッドでアップロードされたファイルにアクセスし、isValidメソッドで正常にアップロードされたかを確認します。
  • 正常に行われたらstoreメソッドで保存します。
  • 保存したときにはパスの情報もpathに入っているのでファイルを呼び出すときにはbasenameを使ってファイル名のみ呼び出します。
  • アップロードがうまくいってないのであれば送信したデータをセッションに入れて元のページに戻るように設定します。

これで画像ファイルが保存できるようになりました。
ちなみに保存される場所は下記のpublicディレクトリになっています。

─── strage
    ├── app
         ├── public

あとはTerminalからstorageを公開できるように設定するだけです。

画像ファイルへのリンクの設定

mbp:training user$ php artisan storage:link
The [/Users/user/code/training/public/storage] link has been connected to [/Users/user/code/training/storage/app/public].
The links have been created.

これでpublic/storage から storage/app/public へシンボリックリンクが張られ、Webからアクセスできるようになります。

確認

では、確認して行きます。

ファイルを選択、から画像ファイルを選択しSubmitをクリックします。

うまく画像がアップロードされました。

保存した画像を呼び出す方法

画像をアップロードできましたが、これではページを移動して戻って来た時に表示されません。そのため、usersテーブルにpictureカラムを作ってそこから画像を呼び出すように設定して行きます。

カラムの設定

まずはusersテーブルにpictureカラムを追加します。

mbp:training user$ php artisan make:migration add_picture_users
Created Migration: 2020_07_10_074117_add_picture_users

では、カラム追加のためのマイグレーションファイルを編集して行きます。

public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('picture', 100);
        });
    }

こんな感じでいいかと思います。
では、マイグレーションを実行します。

mbp:training user$ php artisan migrate
Migrating: 2020_07_10_074117_add_picture_users
Migrated:  2020_07_10_074117_add_picture_users (0.04 seconds)

うまく行きました。
TablePlusで確認します。

うまくできてますね。
では、画像ファイルの保存をこのカラムにするためにPictureController.phpを編集して行きます。

コントローラーの設定

public function store($id, Request $request){
    	$this->validate($request, [
            'picture' => 'required|file|image|mimes:jpeg,png,jpg,gif|max:1148'
            ]);
    	if ($request->file('picture')->isValid([])) {
            $path = $request->file('picture')->store('public');
            $user = User::find($id);
            $user->picture = basename($path); //追加
            $user->save(); //追加
            return view('comment')->with([
              'filename' => basename($path), //削除
             'user' => $user,
            ]);

        } else {
            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['file' => '画像がアップロードされていないか不正なデータです。']);
        }

これでusersテーブルのpictureに保存されるのでビューの$userから画像ファイルが取れるはずです。
なので、ビューも編集して行きます。

ビューの設定

@isset ($user->picture)
	   <div>
	       <img src="{{ asset('storage/' . $user->picture) }}">
	   </div>
@endisset

$filenameではなく、$user->pictureで画像ファイルをとって来ています。

確認

では、確認してみましょう。

ファイルを選択してSubmitをクリックします。

うまく行きました。さらに、他のページに行って戻って来ても画像が表示されているようになっています。

まとめ

今回はデータベースに画像を保存して呼び出す方法を紹介しました。

画像がアップロードできれば、あとは基本通りに行えば大丈夫ですね。過去の記事を参考にしてもらえれば問題ないかと思います。

関連記事