Laravelで画像をアップロードしたいけど、どうすればいんだろう….
この記事では上記の悩みを解決します。
休日で空いた時間の暇つぶしを探せるアプリを公開しています。
Laravelで画像をアップロードする手順
Laravelで画像をアップロードする手順は以下です。
php artisan storage:linkを実行
ファイルのアップロードが必要な場合、以下のコマンドを実行します。
% php artisan storage:link
The [/var/www/public/storage] link has been connected to [/var/www/storage/app/public].
The links have been created.
publicディレクトリ配下にstorageが作成されます。※routesの次ぐらいに作成されるかと。
画像パスのカラムを用意する
まずは以下のようにテーブルに画像を保存するカラムを用意します。(img_path※カラム名はなんでもいい)
マイグレーションファイルはこんな感じ。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('img_path');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
php artisan migrateでitemsテーブルを作成します。
モデルにはテーブルの定義と、fillableで登録・更新できるカラムを指定しておきます。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
use HasFactory;
protected $table = 'items';
protected $fillable = [
'img_path',
];
}
コントローラーは以下のようにindex,create,storeアクションを用意します。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Item;
class ItemController extends Controller
{
public function index()
{
return view('item.index');
}
public function create(Request $request)
{
return view('item.create');
}
public function store(Request $request)
{
}
}
ルーティングは以下のように設定します。
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ItemController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', [ItemController::class, 'index'])->name('item.index');
Route::get('/create', [ItemController::class, 'create'])->name('item.create');
Route::post('/store', [ItemController::class, 'store'])->name('item.store');
画像を投稿できるフォームを用意
画像を投稿できるフォームを作成します。
画像アップロードする時のポイントは2つ!
enctype=”multipart/form-data”とtype=fileにすることです。
<form action="{{ route('item.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="img_path">
<input type="submit" value="アップロード">
</form>
画像アップロード機能
画像アップロード機能storeアクションで画像のアップロード機能を実装していきます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Item;
class ItemController extends Controller
{
public function index()
{
return view('item.index');
}
public function create(Request $request)
{
return view('item.create');
}
public function store(Request $request)
{
// 画像フォームでリクエストした画像情報を取得
$img = $request->file('img_path');
}
}
フォームでtype=”file”としているので、file()でリクエストされたファイル情報を取得します。
一時的にstorageにファイルを保存します。
public function store(Request $request)
{
// 画像フォームでリクエストした画像を取得
$img = $request->file('img_path');
// storage > public > img配下に画像が保存される
$path = $img->store('img','public');
}
store()で、アップロードした画像を一時的に保存できます。
上記では、storage下のpublic下のimgディレクトリに画像を保存できます。
以下のようにランダムなファイルパスで画像を保存できます。
DBに画像ファイルを保存します。
public function store(Request $request)
{
// 画像フォームでリクエストした画像を取得
$img = $request->file('img_path');
// storage > public > img配下に画像が保存される
$path = $img->store('img','public');
// DBに登録する処理
Item::create([
'img_path' => $path,
]);
}
createでDBに登録できます。
以下のようにimg_pathにデータが登録できます。
上記でもいいのですが、より処理を実践っぽく保存する条件を追加します。
public function store(Request $request)
{
// 画像情報がセットされていれば、保存処理を実行
if (isset($img)) {
// storage > public > img配下に画像が保存される
$path = $img->store('img','public');
// store処理が実行できたらDBに保存処理を実行
if ($path) {
// DBに登録する処理
Item::create([
'img_path' => $path,
]);
}
}
}
最後に一覧画面にリダイレクトするようにします。
public function store(Request $request)
{
// 画像フォームでリクエストした画像を取得
$img = $request->file('img_path');
// 画像情報がセットされていれば、保存処理を実行
if (isset($img)) {
// storage > public > img配下に画像が保存される
$path = $img->store('img','public');
// store処理が実行できたらDBに保存処理を実行
if ($path) {
// DBに登録する処理
Item::create([
'img_path' => $path,
]);
}
}
// リダイレクト
return redirect()->route('item.index');
}
一覧画面で画像を表示させる
一覧画面にリダイレクトするので、一覧画面のindexアクションに追記します。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Item;
class ItemController extends Controller
{
public function index()
{
// itemsテーブルのデータを全て取得
$items = Item::get();
return view('item.index', compact('items'));
}
public function create(Request $request)
{
return view('item.create');
}
public function store(Request $request)
{
// 画像フォームでリクエストした画像を取得
$img = $request->file('img_path');
// 画像情報がセットされていれば、保存処理を実行
if (isset($img)) {
// storage > public > img配下に画像が保存される
$path = $img->store('img','public');
// store処理が実行できたらDBに保存処理を実行
if ($path) {
// DBに登録する処理
Item::create([
'img_path' => $path,
]);
}
}
// リダイレクト
return redirect()->route('item.index');
}
}
一覧画面に画像を表示させます。
<h1>一覧画面</h1>
@foreach ($items as $item)
<img src="{{ Storage::url($item->img_path) }}" width="25%">
@endforeach
Storage::urlでstorage > app > publicの画像ファイルにアクセスし、パスを取得できます。
注意点としては、そもそもstorage配下に保存した画像がなければ、いくらDBに画像を保存していてそれを呼び出しても画像は表示されません。
画像ファイルを選択し、アップロードをクリックすると、保存処理が実行されて一覧画面にリダイレクトされます。
一覧画面にリダイレクトされると、先ほどアップロードした画像が表示されます。
休日で空いた時間の暇つぶしを探せるアプリを公開しています。
コメント