質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.78%

laravel 複数画像 アップロードしたいです

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,241

score 28

前提・実現したいこと

1枚の画像アップロードはできるのですが、複数画像をアップロードしようとすると配列をどのように扱ってよいかわからず実装できず困っています。
create.blade.phpの画像nameはimage1~4で実装しています。image[]にしている参考サイトが多く色々試してみたのですがうまく実装できず今の現状へ至っています。
ImagesControllerのisset($form[ここにどうやって配列を持ってくればよいか])
$path = $request->file(ここをどうやって配列を持ってくればよいか)->store('public/image');
がわかりません。
他にもこのままでは実装できない原因があればアドバイスを頂きたいです。
よろしくお願い致しますm(__)m

itesテーブル

<?php

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

class CreateItemsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('items', function (Blueprint $table) {
            $table->bigIncrements('id'); //主キー
            $table->string('item_name', 100);
            $table->string('explanation', 255)->default('');
            $table->integer('amount');   //amout=金額
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()    //関数downには、マイグレーションの取り消しを行う為のコードを書きます

    {
        Schema::dropIfExists('items');//ここでは、もしitemsというテーブルが存在すれば削除すると書かれています
    }
}


item_photosテーブル

<?php

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

class CreateItemPhotosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('item_photos', function (Blueprint $table) {
            $table->Bigincrements('id');
            $table->Biginteger('item_id')->unsigned();  //外部キー属性の時よく使う、符号なしに設定
            $table->foreign('item_id')->references('id')->on('items'); //外部キー参照
            $table->string('image_path')->nullable()->default('');  //->nullable()という記述は、画像のパスは空でも保存できます、という意味
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('item_photos');
    }
}


Itemモデル

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    protected $fillable = [
        'item_name',
        'explanation',
        'amount',
        'inventory_control',
    ];

    public static $rules = array(
        'item_name' => 'required',
        'explanation' => 'required',
        'amount' => 'required',
        'inventory_control' => 'required'
    );



    public function photos()
    {
        return $this->hasMany('App\ItemPhoto');
    }

}


ItemPhotoモデル

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class ItemPhoto extends Model
{

    protected $fillable = ['item_id', 'image_path'];

    public static $rules = array(
        'image_path' => 'required',
    );

    public function item()
    {
        return $this->belongsTo('App\Item');
    }
}


ImagesController

<?php

namespace App\Http\Controllers\Admin;

use Symfony\Component\HttpFoundation\Response;
use Illuminate\Http\Request;
use App\Item;
use Storage;
use Carbon\carbon;
use App\ImagesHistory;
use App\Http\Controllers\Controller;
use App\Admin;
use \InterventionImage;
use App\ItemPhoto;

class ImagesController extends Controller
{
 public function create(Request $request)
    {
        $this->validate($request, Item::$rules);  //Itemモデルでバリデーションした(item_name,explanation,amount,inventory_control,item_pic_path)
        // $this->validate($request, ItemPhoto::$rules);
        $form = $request->all(); //$request->all()は全入力を連想配列で取得

        $item = new Item(); //新規Itemインスタンス作成

        // フォームから送信されてきた_tokenを削除する、一時保存を削除すると考えてよい?
        unset($form['_token']);

        $item->fill($form)->save(); //先にitemのレコードがないと子であるitem_photosは入れられないため、データベースへ保存

        $item_photos = array(); //空の配列用意
        $form[] = 'image1'; //list.blade.phpのnameから取得して$form配列に入れる
        $form[] = 'image2';
        $form[] = 'image3';
        $form[] = 'image4';

        if(isset($form['image1'])){ //issetは変数に値がセットされているか確認する方法、つまり$file_nameに'image_path'があるか確認している
              $path = $request->file('image1')->store('public/image'); //file()内にview側の画像のnameを書く、->store()で画像をpublic/storage/image保存
              $item->image_path = basename($path);//basenameはパスの/以降の文字列を全て取得
              $files = $request->file('image_path'); //file('読み込みたい変数、カラムなど文字列ならok') 

              $item_photo = new ItemPhoto(); //ItemPhotoインスタンス作成
              $item_photo->fill(["image_path"=>$form]);
              $item_photos[] = $item_photo; //各item_photoを用意した$item_photosに代入する
              InterventionImage::make($files)->resize(100, 100)->save(public_path()."/image/resize_image/". $item_photo->image_path);
        }                //App::make()取得できる

        // フォームから送信されてきたimageを削除する
        unset($form['image_path']);

        if (!empty($item_photos))
        {
            $item->photos()->saveMany($item_photos);//photos()の所は親(Itemモデル)のphotos()アクションでリレーションしているためphotos()を使う
        }

        return redirect('admin/images/create')->with('flash_message', '商品を追加しました');
    }


create.blade.php

<form method="post" action="{{ route('item_regi') }}" enctype="multipart/form-data">
<div class="form-group row mt-5">
                               <label class="col-md-2">画像1</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image1" multiple="multiple">
                                   </div>
                           </div>
                           <div class="form-group row mt-5">
                               <label class="col-md-2">画像2</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image2">
                                   </div>
                           </div>
                           <div class="form-group row mt-5">
                               <label class="col-md-2">画像3</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image3">
                                   </div>
                           </div>
                           <div class="form-group row mt-5">
                               <label class="col-md-2">画像4</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image4">
                                   </div>
                           </div>
                           {{ csrf_field() }}
                     <input type="submit" class="btn btn-primary mt-3" value="商品登録">
</form>


list.blade.php

@foreach($items as $item)
   <tr>
      <th>{{ $item->id }}</th>
         <td>{{ Str::limit($item->item_name, 10) }}</td>
         <td>{{ Str::limit($item->amount, 5) }}円</td>
         <td>{{ Str::limit($item->explanation, 200) }}</td>
         <td>{{ Str::limit($item->inventory_control, 5) }}</td>

         @foreach($item->photos as $photo)
         <td>
         <a href="/items/{{ $item->id }}"><img src="{{ asset('/image/resize_image/' . $photo->image_path) }}" alt=""></a>
         </td>
         @endforeach
   </tr>
@endforeach

`

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

ImagesController

public function create(Request $request)
    {
        $this->validate($request, Item::$rules);  //Itemモデルでバリデーションした(item_name,explanation,amount,inventory_control,item_pic_path)
        $form = $request->all(); //$request->all()は全入力を連想配列で取得

        $item = new Item(); //新規Itemインスタンス作成


        // フォームから送信されてきた_tokenを削除する
        unset($form['_token']);
        // フォームから送信されてきたimageを削除する
        unset($form['image_path']);
        // データベースに保存する

        $item->fill($form)->save(); //先にitemのレコードがないと子であるitem_photosは入れられない
        $dt = Carbon::now()->format('Y-m-d-H:i:s')."." . substr(explode(".", (microtime(true) . ""))[1], 0, 3);

        $item_photos = array(); //空の配列用意
            for($i=1; $i<=4; $i++){ 
            $file_name = "image_path".$i; //images_path1~4を準備して$file_nameに代入
                  if(isset($request->$file_name)){ //issetは変数に値がセットされているか確認する方法、つまり$file_nameに'image_path'があるか確認している
                      $files = $request->file($file_name); //file('読み込みたい変数、カラムなど文字列ならok') 
                      $path = $request->$file_name->storeAs('public/image', $file_name.$dt.'.png'); //画像をストレージに保存

                      $item->image_path = basename($path);
                      $item_photo = new ItemPhoto(); //ItemPhotoインスタンス作成
                      $item_photo->fill(["image_path"=>$file_name.$dt.'.png']);
                      $item_photos[] = $item_photo; //各item_photoを用意した$item_photosに代入する
                      InterventionImage::make($files)->resize(100, 100)->save(public_path()."/image/resize_image/". $item_photo->image_path);
                  }
            }
        if (!empty($item_photos))
        {
            $item->photos()->saveMany($item_photos);//photos()の所は親(Itemモデル)のphotos()アクションでリレーションしているためphotos()を使う
        }
        return redirect('admin/images/create')->with('flash_message', '商品を追加しました');
    }


view側は変更せず、ItemPhotoテーブルのimage_pathに入る名前を変更する事で1商品につき4枚ずつ写真を登録する事ができました。
image_pathに登録される名前には日付、時間、micro秒を登録して被らないようにしました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

<form method="post" action="{{ route('item_regi') }}" enctype="multipart/form-data">
<div class="form-group row mt-5">
                               <label class="col-md-2">画像1</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image[]">
                                   </div>
                           </div>
                           <div class="form-group row mt-5">
                               <label class="col-md-2">画像2</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image[]">
                                   </div>
                           </div>
                           <div class="form-group row mt-5">
                               <label class="col-md-2">画像3</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image[]">
                                   </div>
                           </div>
                           <div class="form-group row mt-5">
                               <label class="col-md-2">画像4</label>
                                   <div class="col-md-10">
                                       <input class="form-control-file" type="file" name="image[]">
                                   </div>
                           </div>
                           {{ csrf_field() }}
                     <input type="submit" class="btn btn-primary mt-3" value="商品登録">
</form>

まず、bladeをこうするところからですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/23 00:00

    すいません。
    →それを変更した上で、それをヒントに考えて欲しいと言う意図で回答しているのですけど。
    が見れてなかったです。
    もう一度考えてみます!

    キャンセル

  • 2020/01/23 00:01

    > $request->file('image1')

    ここには画像の情報入っていたんでしょ?

    だったら、$request->file('image') こうしてみた時にどんな値になっているかをデバッグすればわかるんじゃないでっすか?

    $files = $request->file('image');
    dd($files);

    とでもしてみて、どうなるかを確認してみる。

    キャンセル

  • 2020/01/23 00:15

    ありがとうございます。
    ddを使った事ないのでそこからやってみます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る