phplaravelsoft-delete

Laravel restore() method inserts new record in database table


I'm trying to implement a feature in which the user can set favourites in his profile. This is the favourites table:favourites table I'm using soft delete for the favourite model and in the controller i first check if there is a existing record or trashed one and then i restore it.But in my table there is a new inserted record identical to the original one except the value of updated_at and delete_atduplicated record.How can i fix this in order to be just one record?

This is inside my controller method:

`public function setUserFavourite(Request $request): \Illuminate\Http\JsonResponse
    {
        $user = auth()->user();
        $contentModel = $request->input('contentModel');
        $contentId = $request->input('contentId');


        $existingFavourite = $user->favourites()
            ->byContentAlias($contentModel)
            ->where('content_id', $contentId)
            ->first();

        if ($existingFavourite) {
            if ($existingFavourite->trashed()) {
                $existingFavourite->restore();
                \Log::info('Favourite restored:', ['favourite_id' => $existingFavourite->id]);
                return $this->success(new FavouriteResource($existingFavourite), 'Content added to favourites');
            }

            return $this->generalError('This Content is already a favourite');
        }
        $favourite = new Favourite(['user_id' => $user->id]);

        switch ($contentModel){
            case 'Venue':
                $venue = Venue::find($contentId);
                $favourite->favourable()->associate($venue);
                break;

            case 'Organiser':
                $organiser = Organiser::find($contentId);
                $favourite->favourable()->associate($organiser);
                break;

            case 'Event':
                $event = Event::find($contentId);
                $favourite->favourable()->associate($event);
                break;

            default:
                return $this->generalError('Invalid Content Model');
        }
        $favourite->save();
        \Log::info('Favourite created:', ['favourite_id' => $favourite->id]);
        return $this->success(new FavouriteResource($favourite),'Content added to favourites');

    }`

`This is my Favourite Model:

`<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class Favourite extends Model
{
    use HasFactory;
    use SoftDeletes;

    protected $table = 'favourites';

    protected $fillable = [
        'user_id','content_model','content_id'
    ];

    public function favourable(): MorphTo
    {
        return $this->morphTo(__FUNCTION__,'content_model','content_id');
    }

    public function scopeByContentAlias($query, $contentAlias)
    {
        $contentModelNamespace = "App\Models\\" . ucfirst($contentAlias);
        return $query->where('content_model', $contentModelNamespace);
    }

}`

And this is my User Model:

`class User extends Authenticatable implements MustVerifyEmail
{
    use HasRoles ,HasApiTokens, HasFactory, Notifiable;


   public function favourites(): HasMany
    {
        return $this->hasMany(Favourite::class,'user_id');
    }


}`

Api.php routes:

Route::controller(FavouriteController::class)->group(function(){
    Route::post('set-favourite','setUserFavourite');
    Route::get('get-favourites/{contentModel?}','getUserFavourites');
    Route::delete('remove-favourite', 'removeUserFavorite');
});

I have tried Logging the id of the inserted records

[2024-02-14 13:00:40] local.INFO: Favourite created: {"favourite_id":17} 
[2024-02-14 13:01:39] local.INFO: Favourite created: {"favourite_id":18} 
[2024-02-14 13:08:52] local.INFO: Favourite created: {"favourite_id":19} 

Solution

  • "Laravel restore() method inserts new record" - Incorrect; your code is never actually making it to the $existingFavourite->restore(); call.

    When you query for $existingFavourite, you're not including ->withTrashed(), so if the record you're expecting to find is soft deleted, you'll never hit either of the if() statements (if ($existingFavourite) and if ($existingFavourite->trashed())). $existingFavourite is null, and if (null) will not enter the body of that if statement.

    Change your code to:

    $existingFavourite = $user->favourites()
    ->byContentAlias($contentModel)
    ->where('content_id', $contentId)
    ->withTrashed() // Add this line to include query for soft deleted records
    ->first();
    

    Documentation for reference:

    https://laravel.com/docs/10.x/eloquent#restoring-soft-deleted-models