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 にシンボリックリンクが作成されます。
動作確認
さて、ここまで実装すればブラウザからファイルアップロードができるようになっているはずです。