Help us understand the problem. What is going on with this article?

Laravelで画像ファイルアップロードをする簡単なサンプル

More than 1 year has passed since last update.

Laravelを使ってユーザーのavatar画像をアップロードする想定で、アップロード機能のサンプルを実装してみます。

開発環境

  • Laravel 5.3
  • Laravel Homestead
    • PHP7.1系
    • MySQL 5.7系
    • Nginx

ベースとなる画面をmakeする

$ php artisan make:auth

するとこれだけのファイルが書き出されます。

    new file:   app/Http/Controllers/HomeController.php
    new file:   resources/views/auth/login.blade.php
    new file:   resources/views/auth/passwords/email.blade.php
    new file:   resources/views/auth/passwords/reset.blade.php
    new file:   resources/views/auth/register.blade.php
    new file:   resources/views/home.blade.php
    new file:   resources/views/layouts/app.blade.php
    modified:   routes/web.php

DBのmigrationも実行しておきましょう。

$ php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table

ここまでやると、ブラウザからアクセスしたときに右上に REGISTER というリンクができているので、画面に従ってユーザー登録&ログインします。

(前提環境準備終了)これからが本番です。

フォームを作成する

ファイルアップロードするフォームを追加します。
ここでは説明を省略するため、Dashboard画面に追加しますがユーザー情報変更画面などに追加するのが良いでしょう。

(抜粋)resources/views/home.blade.php
{!! Form::open(['url' => '/upload', 'method' => 'post', 'files' => true]) !!}

{{--成功時のメッセージ--}}
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
{{-- エラーメッセージ --}}
@if ($errors->any())
    <div class="alert alert-danger">
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
    </div>
@endif

<div class="form-group">
    @if ($user->avatar_filename)
        <p>
            <img src="{{ asset('storage/avatar/' . $user->avatar_filename) }}" alt="avatar" />
        </p>
    @endif
    {!! Form::label('file', '画像アップロード', ['class' => 'control-label']) !!}
    {!! Form::file('file') !!}
</div>

<div class="form-group">
    {!! Form::submit('アップロード', ['class' => 'btn btn-default']) !!}
</div>
{!! Form::close() !!}

Routeを追加

(末尾に追加)routes/web.php
Route::post('/upload', 'HomeController@upload');

Controllerを実装

リファクタリングの余地はたくさんありますが、ここではかんたんな実装ということでControllerに処理を書いていきます。

app/Http/Controllers/HomeController.php
<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $user = User::find(auth()->id());

        return view('home', compact('user'));
    }


    /**
     * ファイルアップロード処理
     */
    public function upload(Request $request)
    {
        $this->validate($request, [
            'file' => [
                // 必須
                'required',
                // アップロードされたファイルであること
                'file',
                // 画像ファイルであること
                'image',
                // MIMEタイプを指定
                'mimes:jpeg,png',
                // 最小縦横120px 最大縦横400px
                'dimensions:min_width=120,min_height=120,max_width=400,max_height=400',
            ]
        ]);

        if ($request->file('file')->isValid([])) {
            $filename = $request->file->store('public/avatar');

            $user = User::find(auth()->id());
            $user->avatar_filename = basename($filename);
            $user->save();

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

Migration

usersテーブルにカラムを追加してavatar画像のファイル名を保存することにしたので、Migrationファイルを作成します。

$ php artisan make:migration add_avater_filename --table=users
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddAvatarFilename extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('avatar_filename', 100);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('avatar_filename');
        });
    }
}

マイグレーションファイルを記述したら、実行します。

$ php artisan migrate

storageを公開するためのシンボリックリンク作成

$ php artisan storage:link

このコマンドで public/storage から storage/public にシンボリックリンクが作成されます。

動作確認

さて、ここまで実装すればブラウザからファイルアップロードができるようになっているはずです。

スクリーンショット 2017-01-06 13.29.15.png

makies
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。東京(三軒茶屋)/京都(四条烏丸)/札幌/大阪/福岡に展開中!Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした