Laravel Eloquent insert 3 rows at once with timestamp

10,212

Solution 1

insert() is a part of Query Builder, so it doesn't use Eloquent features.

You can't pass 3 items to create() method, only one. And using create() inside loops is terrible idea.

You should add these fields manually when doing bulk insertion:

[
    'application_id'    => $applications[0]->a_id,
    'group_id'          => $group->id,
    'created_at'        => Carbon::now(),
    'updated_at'        => Carbon::now(),
],

Solution 2

You may use dateTime class :

[
    'application_id'    => $applications[0]->a_id,
    'group_id'          => $group->id,
    'created_at'        => new \dateTime,
    'updated_at'        => new \dateTime,
],
Share:
10,212
Benyi
Author by

Benyi

Hi, I'm Benyi, from Taiwan.

Updated on June 25, 2022

Comments

  • Benyi
    Benyi almost 2 years

    I'm making a site with Laravel 5.2

    I would like to do is

    • INSERT 3 rows at the same time
    • The new 3 rows have to contain timestamp created_at updated_at.

    With the Query Builder method insert, Yes, it does insert 3 rows at once by passing an array like:

    GroupRelation::insert([
        [
            'application_id'    => $applications[0]->a_id,
            'group_id'          => $group->id,
        ],
        [
            'application_id'    => $applications[1]->a_id,
            'group_id'          => $group->id,
        ],
        [
            'application_id'    => $applications[2]->a_id,
            'group_id'          => $group->id,
        ],
    ]);
    

    The code above works fine. But this cannot touch the timestamp. Which means the created_at updated_at will be null.

    However, if I changed the method insert to create:

    GroupRelation::create([
       ... 
    ]);
    

    It received the error:

    ErrorException in Model.php line 2983:
    preg_match() expects parameter 2 to be string, array given
    

    If I'm not wrong, it seems like create can just accept 1 row at the same time, right?

    I know insert is not a part of Eloquent. Eloquent fires timestamps but Query Builder does not.

    So my questions are:

    1. insert method can accept 3 rows at one time, but how can I fire the timestamp manually?
    2. By 1. I've tried to add 'created_at' => date('Y-m-d H:i:s'), at each items of the array. But the controller is unclear and horrible.
    3. How can I pass an array of 3 items to create method in order to fire timestamps?
    4. Is it a good idea to call create inside the loops?

    PS. protected $guarded = [] was assigned to empty array so would not receive Mass Assignment Exception.

    Thank you so much.

  • Benyi
    Benyi over 7 years
    Thanks! Yes, I've done that! But I have 3 rows. As you see, I have 3 items of the array. Each of them is almost same and a little difference of $applications index among them. If I manually add created_at updated_at to the array set, the code is triplicate. Any further ideas?
  • Kyslik
    Kyslik over 7 years
    I am sure there is already question like that, why instead of searching for duplicate you choose to answer? I am just curious...
  • Alexey Mezenin
    Alexey Mezenin over 7 years
    @Benyi you can create an array and then just iterate over it and add timestamps to each item. It's the best solution you've got.
  • Alexey Mezenin
    Alexey Mezenin over 7 years
    @Kyslik usually people who post links to 'duplicates', post links to not really related questions. I hate that and prefer to answer questions with related code and explanation. If you found helpful similar question, please post the link.
  • Benyi
    Benyi over 7 years
    Thanks @AlexeyMezenin and @Kyslik! This is a good idea for me. Hope AlexeyMezenin's answer and suggestion are helpful to that people who are confusing with timestamp not fired, and create no bulk insertion. Thank you so much.
  • Benyi
    Benyi over 7 years
    @AlexeyMezenin By your suggestion provided yesterday, I've used array_walk() walking through each of the item, and create new sub-items (created_at, group_id...) of that item in the closure. Finally I got the finished array with no triplicate same code. That is what I want. :)
  • Alexey Mezenin
    Alexey Mezenin over 7 years
    Glad it was helpful. )
  • Benyi
    Benyi over 7 years
    Thank you for answering. In this question, the way to get current time is not relevant. It's about timestamp not updating by insert() method. And it can't insert more than 1 row by create method which is able to update timestamp.