spatie / laravel-data

Powerful data objects for Laravel
https://spatie.be/docs/laravel-data/
MIT License
1.28k stars 209 forks source link

When using app() Container method with partial $model->fill() data, validation failes #830

Closed eelco2k closed 3 months ago

eelco2k commented 3 months ago

✏️ Describe the bug Find a record of a Model, use the ->fill() method for updating that model and then use the DTO for validating. The validateAndCreate($model) method only sees the $model = Model::find($id); initial data of the model and so returns validation errors of the not added fields in ->fill()

↪️ To Reproduce Simple TestModel with 2 fillable fields: 'title' and 'description'. Request is a POST request with an id param in route uri. postData is: { title: "updated title" }. (so NO description)


public function handle(Request $request)
 {

    $id = $request->route('id');
    $model = TestModel::find($id);
    $modelArrOrig = $model->toArray(); // ['title' => 'original title', 'description' => 'original description'];
    $model->fill($request->all());

    $modelArrNew = $model->toArray(); // ['title' => 'updated title', 'description' => 'original description'];

    // !important in this scenario... resolve from container
    $dto = app(TestData::class);

    $dtoModel = $dto::validateAndCreate($model);  // <-- Failes Validation: description is required
    $dtoModel2 = $dto::validateAndCreate($modelArrNew); // <-- Failes Validation: description is required

    $dtoModelCorrect = TestData::validateAndCreate($model); // <-- Success
}

✅ Expected behavior As the $model is filled with new data but also has the original data from the model the validation failure of description should not occur. even when converting it to an Array (as in $modelArrNew) all the required fields are in the array.

Maybe i'm just doing something wrong here..

🖥️ Versions

Laravel: 10.48.14 Laravel Data: 4.7.0 PHP: 8.3.7

rubenvanassche commented 3 months ago

This is quite logical, since you're resolving data from the container, the request is automatically validated based upon the data object. Only one key is provided so it fails on the second one.

In this case, create a new data object once your model isn saved.

eelco2k commented 3 months ago

Yes, silly me. Already figured it out. Thanks for the clarification though. ☺️