Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

johnef_sh's avatar

Laravel replicate works but not inserting into database

I am trying to replicates a record in my database here is my controller

private Receiver $receiver;

public function __construct()
    {
        $this->receiver = new Receiver();
        ....
    }

$this->receiver = $receiverData;
        if ($reversed) {
            $receiver = Receiver::find($receiverData['id']);
            $new_receiver = $receiver->replicate();
            $this->receiver = $new_receiver;
        } else {
            $this->receiver->user_id = $receiverData->user_id = auth()->id();
        }

        $this->receiver->save();
        dd($this->receiver);

Now the debug shows correct results

#attributes: array:11 [▶
    "user_id" => 1
    "city_id" => 2
    "name" => "Mohamed"
    "address" => "Al noor st. 15 city"
    "phone" => "054545488877"
    "email" => "[email protected]"
    "latitude" => null
    "longitude" => null
    "updated_at" => "2023-11-26 18:09:38"
    "created_at" => "2023-11-26 18:09:38"
    "id" => 148
  ]

But it dose not insert any records to my database any idea what could be the issue here.

0 likes
4 replies
vincent15000's avatar

The second line overwrites the first one.

$this->receiver = new Receiver();
$this->receiver = $receiverData;

Are you sure that $receiverData is a Receiver model ?

1 like
kokoshneta's avatar

It’s very hard to get the meaning of your code, because it’s written in quite an unstructured manner, and the variable names don’t make things any easier.

$this->receiver = new Receiver();
$this->receiver = $receiverData;

Here you set $this->receiver to a blank model, then immediately overwrite it to whatever $receiverData is (going by your dd() output, probably an array).

 

if ($reversed) {
	$receiver = Receiver::find($receiverData['id']);
	$new_receiver = $receiver->replicate();
	$this->receiver = $new_receiver;
} else {
	$this->receiver->user_id = $receiverData->user_id = auth()->id();
}

Here, depending on $reversed, you either:

  • overwrite $this->receiver again, this time to a model that replicates a model you load from the database based on the array $receiverData
  • or set the user ID property on $this->receiver to the user ID on the object $receiverData, which you set to the current user’s ID

None of that makes any sense at all.

 

In one branch of the if statement, you treat $receiverData as an array; in the other, you treat it as an object. It cannot be both.

In one branch, you’re creating a whole model and replicating it, then saving that model in $this->receiver. In the other, you leave $this->receiver as it is (the contents of $receiverData) and just update a single property.

In one branch, you set the user ID property to be the current user’s ID; in the other, you don’t set it at all (so you’re counting on it being present in $receiverData, I guess?).

Nowhere do you check what $receiverData actually is – if this is data you’re getting from user input, it needs to be validated before you start saving it into models.

 

From your code, it’s impossible to work out what exactly $receiverData is supposed to be, but I’m going to guess that it’s an array of data (not a model) that may or may not be used to create a new model instance, based on the mysteriously named boolean(?) called $reverse. I have no idea what $reverse is supposed to represent, but for its purpose, I’m going to guess that if it’s true, the receiver should be a replica of an existing model; if it’s false, it should be a new model created from the data in $receiverData.

I’m also going to guess that you want to set the user ID to the current user regardless of the value of $reverse.

Assuming those guesses are accurate, this will suffice:

// If $receiverData is from user input, make sure to validate it first here

$this->receiver = ($reversed) ?
	Receiver::findOrFail($receiverData['id'])->replicate() :
	$this->receiver = new Receiver($receiverData)
;

$this->receiver->user_id = auth()->id();
$this->receiver->save();

I’ve used ->findOrFail() instead of ->find() so that the function will throw an exception if there is no existing record matching $receiverData['id'].

2 likes
johnef_sh's avatar

Sorry I didn't clear my code by comments, here is it

I using

  • PHP 8.2
  • MySQL 8
  • Livewire

This part of the code

$this->receiver = new Receiver();

$this->receiver = $receiverData;
        if ($reversed) {
            $receiver = Receiver::find($receiverData['id']);
            $new_receiver = $receiver->replicate();
            $this->receiver = $new_receiver;
        } else {
            $this->receiver->user_id = $receiverData->user_id = auth()->id();
        }

        $this->receiver->save();
        dd($this->receiver);

it's not controller it's service so this receiverData is the data that will fill-out the service values.

Here how the service looks like in the contractor

private Receiver $receiver; // use App\Models\Receiver;

public function __construct()
    {
        $this->receiver = new Receiver();
        .....
    }

Comes to the comment Here, depending on $reversed, you either: Yes $reversed is boolean, and comes true no issue with this.

Actually I have solved the issue and let me tell you what was it. I was trying to replicates the database column without changing anything and that was the main issue. I have read this point in MySQL documentation that if you are trying to insert identical it will update the record. See here

Now I have just changed some values like created_at and updated_at on the replicates and it works fine

and Here is the final working code

// Add receiver
        $this->receiver = $receiverData;
        if ($reversed) {
            $receiver = Receiver::find($receiverData['id']);
            $new_receiver = $receiver->replicate();
            $new_receiver->created_at = Carbon::now();
            $new_receiver->updated_at = Carbon::now();
            $this->receiver = $new_receiver;
        } else {
            $this->receiver->user_id = $receiverData->user_id = auth()->id();
        }
        // Save the receiver to a database.
        $this->receiver->save();

Anyway thanks for all taking time to replay to my question.

1 like
kokoshneta's avatar

@johnef_sh No, that code will not work properly. You have not understood what’s going on.

it's not controller it's service so this receiverData is the data that will fill-out the service values.

It’s completely irrelevant whether this is in a controller or a service. The important thing is whether it’s an array or an object. You treat it as an array in one branch and an object in the other. It cannot be both.

Try your code with $reverse as true, then as false. One of the attempts will throw an error. If $receiverData is an object and $reverse is true, the error will say, “Cannot use object of type [whatever class $receiverData is] as array”. If $receiverData is an array and $reverse is false, it will say, “Attempt to read property user_id on array”.

 

I was trying to replicates the database column without changing anything and that was the main issue. I have read this point in MySQL documentation that if you are trying to insert identical it will update the record. See here

You are not inserting duplicates. The ON DUPLICATE KEY action is only triggered if you attempt to insert a row with an already existing value in a column that has a UNIQUE constraint – in other words, if you’re trying to insert a row that would normally result in an SQL error (“Cannot insert duplicate key row…”). Unless you have a UNIQUE constraint on your created_at and/or updated_at columns, this is not relevant here, and your workaround does nothing.

If you have no UNIQUE constraints (except on the primary key, of course), then you can replicate as many identical models as you want without MySQL updating any existing rows.

1 like

Please or to participate in this conversation.