I need to update records for Guide Steps (Every recipe has steps/instruction and my table was created for storing this data)
I was able to create those records in the db with quite easy syntax:
GuideStep::insert($groupedSteps); // $groupedSteps is an array
But now I need to update those records (and remove unnecessary ones), for this moment I came up with logic that can only update records or create if there is no such records:
foreach ($groupedSteps as $step){
GuideStep::updateOrInsert(
['recipe_id' => $recipeId, 'step_number' => $step['step_number']],
['step_text' => $step['step_text'], 'step_image' => $step['step_image']]
);
}
migration:
Schema::create('guide_steps', function (Blueprint $table) {
$table->id();
$table->foreignId('recipe_id')->constrained()->cascadeOnDelete();
$table->integer('step_number');
$table->text('step_text');
$table->string('step_image')->default('recipes-images/default/default_photo.png');
$table->timestamps();
});
I thought that I’ll be able to use upsert()
but this method requires unique
columns (I don’t have those)
Be grateful for some advices
1. Fetch Existing Steps
First, retrieve all existing steps for the given recipe_id from the database.
2. Compare and Process
Loop through the incoming $groupedSteps to update or insert records, and track which existing steps are still relevant.
3. Delete Unnecessary Steps
After processing, delete any steps that weren’t included in the new $groupedSteps.
Here’s the code:
use App\Models\GuideStep;
public function updateGuideSteps($recipeId, array $groupedSteps)
{
// Step 1: Fetch existing steps for the recipe
$existingSteps = GuideStep::where('recipe_id', $recipeId)
->get()
->pluck('step_number')
->toArray(); // Get array of step_numbers for comparison
// Step 2: Process incoming steps (update or insert)
$incomingStepNumbers = [];
foreach ($groupedSteps as $step) {
GuideStep::updateOrInsert(
[
'recipe_id' => $recipeId,
'step_number' => $step['step_number'],
],
[
'step_text' => $step['step_text'],
'step_image' => $step['step_image'] ?? 'recipes-images/default/default_photo.png', // Fallback to default
]
);
$incomingStepNumbers[] = $step['step_number']; // Track incoming step numbers
}
// Step 3: Delete steps that are no longer in the incoming data
$stepsToDelete = array_diff($existingSteps, $incomingStepNumbers);
if (!empty($stepsToDelete)) {
GuideStep::where('recipe_id', $recipeId)
->whereIn('step_number', $stepsToDelete)
->delete();
}
}