laravelにおけるファイルのアップロード方法

1.目的

画像ファイルのアップロードをできるようにしていきます。

2.必要なもの

なし

3.手順

①itemsテーブルにファイル名保存用カラムを追加するためにマイグレーションファイルを以下のように変更していきます。

class CreateItemsTable extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   {
       Schema::create('items', function (Blueprint $table) {
           $table->id();
           $table->bigInteger('user_id');
           $table->string('name');
           $table->string('url');
           $table->text('text');
           //以下追加
           $table->string('item_img');
           //ここまで
           $table->timestamps();
       });
   }
   /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   {
       Schema::dropIfExists('items');
   }
}

②次にterminalで以下のコマンドを実行しitemsテーブルを再構築します。

% php artisan migrate:refresh

③create.blade.phpを以下のように変更しファイル選択ボタンを表示させます。

@extends('layouts.app')
@section('content')
 <div class="card-body">
   
   

   @include('common.errors')

   <form  enctype="multipart/form-data" action="{{ url('item') }}" method="POST"
   class="form-horizontal">
     @csrf

     <div class="form-group">
       <div class="card-title">
         題目
       </div>
       <div class="col-sm-6">
         <input type="text" name="name" value="{{ old('name') }}" class="form-control">
       </div>
       //以下追加
       <div class="card-title">
         画像
       </div>
       <div class="col-sm-6">
         <input type="file" name="item_img"  >
       </div>
       //ここまで
       <div class="card-title">
         URL
       </div>
       <div class="col-sm-6">
         <input type="integer" name="url" value="{{ old('url') }}" class="form-control">
       </div>
       <div class="card-title">
         text
       </div>
       <div class="col-sm-6">
         <input type="text" name="text" value="{{ old('text') }}" class="form-control">
       </div>

     <div class="form-group">
       <div class="col-sm-offset-3 col-list">
         <button type="submit" class="btn btn-primary">
           Save
         </button>
       </div>
     </div>
     

   </form>
 </div>
 


@endsection

form要素内にあるenctype="multipart/form-data"はファイル送信に必要な属性です。

④show.blade.phpを以下のように変更し投稿された画像を表示できるようにします。

//以下を追記
<div>
 @if ($item->item_img == "")
 <img src= "/upload/751391-3.png" width="100">
 @else 
 <img src= "/upload/{{ $item->item_img }}" width="100"> 
 @endif 
</div>
//ここまで
<div>{{ $item->name }}</div>
<div>{{ $item->url }}</div>
<div>{{ $item->text }}</div>
<form action="{{ url('item/'.$item->id) }}" method="post">
 @csrf
 @method('DELETE')
 <button type="submit" class="btn item-destroy">
   削除
 </button>
</form>
<a href="{{ action('ItemsController@edit', $item->id) }}">編集</a>

if条件を使うことにより画像が投稿されなかったときに表示する画像を決めています。

⑤edit.blade.phpを以下のように変更して編集した時に画像を変更できるようにしています。

@extends('layouts.app')
@section('content')
 <div class="card-body">
   
   
   @include('common.errors')
   <form   action="{{ route('item.update' ,$item->id) }}" enctype="multipart/form-data" method="POST"
   class="form-horizontal">
     @csrf
     @method('PUT')
     <div class="form-group">
       <div class="card-title">
         題目
       </div>
       <div class="col-sm-6">
         <input type="text" name="name" value="{{ $item->name }}" class="form-control">
       </div>
       //以下追加
       <div class="card-title">
         画像
       </div>
       <div class="col-sm-6">
         <input type="file" name="item_img"  >
       </div>
       //ここまで
       <div class="card-title">
         URL
       </div>
       <div class="col-sm-6">
         <input type="integer" name="url" value="{{ $item->url }}" class="form-control">
       </div>
       <div class="card-title">
         text
       </div>
       <div class="col-sm-6">
         <input type="text" name="text" value="{{ $item->text }}" class="form-control">
       </div>
     <div class="form-group">
       <div class="col-sm-offset-3 col-list">
         <button type="submit" class="btn btn-primary">
           Save
         </button>
       </div>
     </div>
     
   </form>
 </div>
 

@endsection

⑥ItemsController.phpを以下のように変更し、ファイルを保存することができるようにします。

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Item;
use Validator;
use Auth;

class ItemsController extends Controller
{
   public function __construct(){
       $this->middleware('auth');
   }
   /**
    * Display a listing of the resource.
    *
    * @return \Illuminate\Http\Response
    */
   public function index()
   {
       $items = Item::where('user_id',Auth::user()->id)->orderBy('created_at','desc')->paginate(5);
       return view('items.index',compact('items'));
       
   }
   /**
    * Show the form for creating a new resource.
    *
    * @return \Illuminate\Http\Response
    */
   public function create()
   {
       return view('items.create');
   }
   /**
    * Store a newly created resource in storage.
    *
    * @param  \Illuminate\Http\Request  $request
    * @return \Illuminate\Http\Response
    */
   public function store(Request $request)
   {
       $validator = Validator::make($request->all(),[
           'name' => 'required',
           'url' => 'required',
           'text' => 'required',
       ]);
       if($validator->fails()){
           return redirect('item/create')
               ->withInput()
               ->withErrors($validator);
       }
       //以下追加
       $file = $request ->file('item_img');  //ここでファイルを取得しています
       if(!empty($file)){
           //ファイルが存在した時
           $filename=$file->getClientOriginalName();      //ファイル名を取得しています
           $move = $file->move('../public/upload/',$filename);  //保存先にファイルを移動させています。
       }else{
           //ファイルがない時
           $filename="";
       }
       //ここまで
       $items = new Item;
       $items->user_id = Auth::user()->id;
       $items->name = $request->name;
       $items->url = $request->url;
       $items->text = $request->text;
       //以下追加
       $items->item_img = $filename;
       //ここまで
       $items->save();
       return redirect('/');
   }
   public function show($id) {
       $item = Item::findOrFail($id);
       return view('items.show')->with('item', $item);
   }
   public function destroy($id){
       $item = Item::findOrFail($id);
       $item->delete();
       return redirect('/');
   }
   public function edit($id){
       $items = Item::where('user_id',Auth::user()->id)->find($id);
       return view('items.edit')->with('item', $items);
   }
   public function update(Request $request,$id){
       $validator = Validator::make($request->all(),[
           'name' => 'required',
           'url' => 'required',
           'text' => 'required',
       ]);
       if($validator->fails()){
           return redirect('item/'.$id.'/edit')
               ->withInput()
               ->withErrors($validator);
       }
       //以下変更
       $file = $request ->file('item_img');
       $items = Item::where('user_id',Auth::user()->id)->find($id);
       $items->name = $request->name;
       $items->url = $request->url;
       $items->text = $request->text;
       if(!empty($file)){
           $filename=$file->getClientOriginalName();
           $move = $file->move('../public/upload/',$filename);
           $items->item_img = $filename;
       }else{
       }
       $items->save();
       return redirect('/');
       //ここまで
   }
   /**
    * Display the specified resource.
    *
    * @param  int  $id
    * @return \Illuminate\Http\Response
    */
   
}

updateアクションでは、ファイルが存在した時だけ保存を行うようにしています。

○このままだと大きいファイルをアップロードすると「The file "dizny.png" exceeds your upload_max_filesize ini directive (limit is 2048 KiB).」といったエラーが出ます。
そのためupload_max_filesizeをおおきくしていきます。

①php.ini ファイルパス ファイル場所 確認をするために以下のコマンドをterminalで実行します。

% php --ini

②terminalで以下のコマンドを実行しphp.iniファイルを開きます。

% sudo vim ①で表示された場所

③iをおし、upload_max_filesizeの値を書き換えます。

4.まとめ

これにてファイルのアップロード機能の実装は、完成です。
以下のようになればOK!!です。
ありがとうございました。

画像1


この記事が気に入ったらサポートをしてみませんか?