CRUD Laravel 在数据库中更新一对多关系

CRUD Laravel Update in database one to many relationship

我有一个包含汽车的 CRUD 应用程序,对于每辆汽车,我都有创建汽车的字段和要上传的图像。一切都很好,我有一对多的关系,对于一辆车我可以有多个图像。当我创建汽车并上传照片时,这些照片会正确存储在数据库和我的 public/images 主管中。问题是当我想更新 par 时,我不知道如何更新数据库中的照片。

这是我的代码,我有更新功能,但我不知道如何进行更新。

My cars table:

    Schema::create('cars', function (Blueprint $table) {
            $table->id();
            $table->string('model');
            $table->integer('seats');
            $table->string('fuel');
            $table->integer('year');
            $table->string('color');
            $table->string('gearbox');
            $table->integer('price');
            $table->string('coinType');
            $table->timestamps();
        });


My images table

    Schema::create('images', function (Blueprint $table) {
            $table->id();
            $table->integer('car_id');
            $table->string('file_name');
            $table->timestamps();
        });


My Car model:

    class Car extends Model
{
    protected $fillable = [
        'model',
        'seats',
        'fuel',
        'year',
        'color',
        'gearbox',
        'price',
        'coinType',
    ];

    public function images()
    {
        return $this->hasMany(Image::class);
    }
    use HasFactory;
}

My Image model:

    class Image extends Model
{
    protected $fillable = [
        'car_id',
        'file_name'
    ];
    
    public function car()
    {
        return $this->belongsTo(Car::class);
    }
    use HasFactory;
}


My edit.blade:

    @extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-sm-8 offset-sm-2">
        <h2 class="display-3">Edit a car</h2>
        <div>
            @if ($errors->any())
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div><br />
            @endif
            <form method="post" action="{{ url('cars/'. $res->id) }}" enctype="multipart/form-data">
                @csrf
                @method('PUT')
                <div class="form-group">
                    <legend>
                        <label for="model" class="col-form-label">Model :</label>
                        <input type="text" class="form-control" id="model" name="model" value="{{ $res->model }}">
                    </legend>
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="seats" class="col-form-label">Seats :</label>
                    </legend>
                    <select name="seats" id="seats" value="{{ $res->seats }}">
                        <option value="2">2</option>
                        <option value="4" selected="selected">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                        <option value="7">7</option>
                        <option value="8">8</option>
                    </select>
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="fuel" class="col-form-label">Fuel :</label>
                    </legend>
                    <select name="fuel" id="fuel" value="{{ $res->fuel }}">
                        <option value="benzine+gpl">benzine+gpl</option>
                        <option value="gpl" selected="selected">diesel</option>
                        <option value="diesel">gpl</option>
                        <option value="diesel+gpl">diesel+gpl</option>
                        <option value="benzine">benzine</option>
                    </select>
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="year" class="col-form-label">Year :</label>
                    </legend>
                    <input type="text" name="year" id="year" value="{{ $res->year }}">
                </div>

                <div class="form-group">
                    <legend>
                        <label for="color" class="col-form-label">Color :</label>
                    </legend>
                    <input type="text" class="form-control" id="color" name="color" value="{{ $res->color }}">
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="gearbox" class="col-form-label">Gearbox :</label>
                    </legend>
                    <select name="gearbox" id="gearbox" value="{{ $res->gearbox }}">
                        <option value="manual">manual</option>
                        <option value="automatic" selected="selected">automatic</option>
                        <option value="semiautomatic">semiautomatic</option>
                    </select>
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="price" class="col-form-label">Price :</label>
                    </legend>
                    <input type="text" class="form-control" id="price" name="price" value="{{ $res->price }}">
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="coinType" class="col-form-label">CoinType :</label>
                    </legend>
                    <select name="coinType" id="coinType" value="{{ $res->coinType }}">
                        <option value="EUR">EUR</option>
                        <option value="LEI" selected="selected">LEI</option>
                        <option value="USD">USD</option>
                    </select>
                </div>

                <div class="form-group ">
                    <legend>
                        <label for="image" class="col-form-label">Upload images :</label>
                    </legend>
                    <input type="file" class="form-control" name="images[]" multiple />
                </div>


                <hr style="height:2px;border-width:0;color:gray;background-color:gray">

                <div class="col-xs-12 col-sm-12 col-md-12 ">
                    <button type="submit" class="btn btn-primary">Add car</button>
                    <a class="btn btn-primary" href="{{ route('cars.index') }}"> Back</a>
                </div>
        </div>
        </form>

        @endsection

我的控制器:

public function store(Request $request)
{
    $request->validate([
        'model' => 'required',
        'year' => 'required',
        'color' => 'required',
        'price'=> 'required',
        'file_name.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
    ]);

    $destionationPath = public_path('/images');
    $images = [];

    $car = new Car();
    $car->model = $request->model;
    $car->seats = $request->seats;
    $car->fuel = $request->fuel;
    $car->year = $request->year;
    $car->color = $request->color;
    $car->gearbox = $request->gearbox;
    $car->price = $request->price;
    $car->coinType = $request->coinType;
  

    $car->save();

    
    if ($files = $request->file('images')) {
        foreach ($files as $file) {
            $fileName = $file->getClientOriginalName();
            $file->move($destionationPath, $fileName);
            $images[] = $fileName;
        }
    }

    foreach ($images as $imag) {
        $image = new Image();
        $image->car_id = $car->id;
        $image->file_name = $imag;
        $image->save();
    }


    return redirect()->route('cars.index')->with('success', 'Car saved !');
}

public function update(Request $request, $id)
{
    $request->validate([
        'model' => 'required',
        'year' => 'required',
        'color' => 'required',
        'price'=> 'required',
        'file_name.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
    ]);

    $destionationPath = public_path('/images');
    $images = [];

    $car = Car::find($id);
    $car->model = $request->model;
    $car->seats = $request->seats;
    $car->fuel = $request->fuel;
    $car->year = $request->year;
    $car->color = $request->color;
    $car->gearbox = $request->gearbox;
    $car->price = $request->price;
    $car->coinType = $request->coinType;
  

    $car->update();

    
    if ($files = $request->file('images')) {
        foreach ($files as $file) {
            $fileName = $file->getClientOriginalName();
            $file->move($destionationPath, $fileName);
            $images[] = $fileName;
        }
    }

    foreach ($images as $imag) {
        //here I don't know what to do
    }


    return redirect()->route('cars.index')->with('success', 'Car updated !');
}

谢谢。

看你的blade文件,你并没有真正显示原始图像,所以用户不能更新图像,他可以插入新图像,旧的应该删除,对吧?

如果你想更新图片,你必须在blade文件中显示原始图片及其ID,所以在后台你可以根据ID找到图片

但这现在应该适合你了:

您可以只检查用户是否上传了任何文件

if ($files = $request->files('images')) {
...

删除所有旧图像

$car->images->each(function($image) {
    // You probabily should be using Storage facade for this
    // this should be the full path, I didn't test it, but if you need add extra methods so it returns the full path to the file
    if (file_exists($destionationPath . '/' . $image->file_name) {
        unset($destionationPath . '/' . $image->file_name);
    }

    $image->delete();
});

然后像在店里一样重新制作图片

foreach ($files as $file) {
    $fileName = $file->getClientOriginalName();
    $file->move($destionationPath, $fileName);
    $images[] = $fileName;
}

foreach ($images as $imag) {
    $image = new Image();
    $image->car_id = $car->id;
    $image->file_name = $imag;
    $image->save();
}