66

I'm currently trying to seed my users table. If I try it like this with 2 rows, it fails. It works fine if I just use a single array instead of the 2 arrays inside the $users array to create some fake data.

What am I doing wrong, what is the proper way to do this?

class UserTableSeeder extends Seeder {

    public function run()
    {
        DB::table('users')->delete();

        $users = [
            ['id' => 1, 'name' => 'Stephan de Vries', 'username' => 'stephan', 'email' => 'stephan-v@gmail.com', 'password' => bcrypt('carrotz124')],
            ['id' => 2, 'name' => 'John doe', 'username' => 'johnny', 'email' => 'johndoe@gmail.com', 'password' => bcrypt('carrotz1243')],
        ];

        User::create($users);
    }

}

Stephan-v
  • 19,255
  • 31
  • 115
  • 201

8 Answers8

83

If you have to use the model you need a loop:

foreach($users as $user){
    User::create($user);
}

Otherwise you can just use DB::table() and insert:

DB::table('users')->insert($users);

Actually you can also call insert() on the model (the resulting query is the same)

User::insert($users);

Note if you choose the insert method you loose special Eloquent functionality such as timestamps and model events.

lukasgeiter
  • 147,337
  • 26
  • 332
  • 270
  • 1
    Was this changed recently? I have a vague memory of being able to do exactly what OP tried, a while ago. – Joel Hinz Feb 18 '15 at 21:24
  • 1
    @JoelHinz Not really. As far as I know it was never possible. It [has been discussed](https://github.com/laravel/framework/issues/1295) but the request was declined. – lukasgeiter Feb 18 '15 at 21:27
  • Thanks it works fine, too bad I couldn't backtrack something like this in the official documentation though. – Stephan-v Feb 18 '15 at 21:28
  • Fair enough. Must be my memory, then. :) – Joel Hinz Feb 18 '15 at 21:28
  • @lukasgeiter that very first part of code with foreach in your answer is very bad. The->create() method will trigger the insert command on spot. Much better way is to use ->make() method and generate the data and then just use one query to insert, after it's generated. – lewis4u Nov 21 '21 at 20:09
54

This works, for Laravel ^5

<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */

    public function run()
    {
        // check if table users is empty
        if(DB::table('users')->count() == 0){

            DB::table('users')->insert([

                [
                    'name' => 'Administrator',
                    'email' => 'admin@app.com',
                    'password' => bcrypt('password'),
                    'created_at' => date('Y-m-d H:i:s'),
                    'updated_at' => date('Y-m-d H:i:s'),
                ],
                [
                    'name' => 'Agency',
                    'email' => 'agency@app.com',
                    'password' => bcrypt('password'),
                    'created_at' => date('Y-m-d H:i:s'),
                    'updated_at' => date('Y-m-d H:i:s'),
                ],
                [
                    'name' => 'End',
                    'email' => 'endcustomer@app.com',
                    'password' => bcrypt('password'),
                    'created_at' => date('Y-m-d H:i:s'),
                    'updated_at' => date('Y-m-d H:i:s'),
                ]

            ]);
            
        } else { echo "\e[31mTable is not empty, therefore NOT "; }

    }
}
lewis4u
  • 14,256
  • 18
  • 107
  • 148
  • 9
    This command somehow only inserts the first row and gives no error – gray_15 May 20 '19 at 03:40
  • @gray_15 not to me! – giovannipds Oct 23 '19 at 15:12
  • In case me or someone else with the same error I was having come here in the future, it's important to specify the column name of each inserting (I wasn't, so it was giving me an error). – giovannipds Oct 23 '19 at 15:13
  • @gray_15 I had the same thing. Yet if I move the array of users out of the insert and just do insert($users) it works fine. – Egnaro Jan 03 '20 at 19:48
  • 4
    There shouldn't be a difference between directly passing the array or putting it in a variable first. But if you do it directly, don't forget to add the actual array brackets. I.e. [a => 1, b=>2], [a=>3, b=>4] doesn't work. Ensure you do [[a => 1, b=>2], [a =>3, b =>4]] so you are passing in an array of records. Otherwise you're passing all but the first as a parameter to insert instead. – Ivo Jansch Oct 26 '20 at 15:51
  • I was enduring the same problem in Laravel 8, and my problem was solved by this answer. The thing was: I was passing many arrays as parameter to the ```insert``` method, when I should be passing ONE array of arrays. Just added the first and last brackets, and it's done. – César Rodriguez Dec 10 '21 at 17:40
11

create() is used to store only one record. To store multiple records you should use insert() instead of create(). So the code will look like this:

class UserTableSeeder extends Seeder {

  public function run()
  {
    DB::table('users')->delete();

    $users = [
        ['id' => 1, 'name' => 'Stephan de Vries', 'username' => 'stephan', 'email' => 'stephan-v@gmail.com', 'password' => bcrypt('carrotz124')],
        ['id' => 2, 'name' => 'John doe', 'username' => 'johnny', 'email' => 'johndoe@gmail.com', 'password' => bcrypt('carrotz1243')],
    ];

    User::insert($users);
  }

}

P.S. insert() function will not store timestamps. i.e.created_by & updated_by fields.

Shrestharikesh
  • 820
  • 7
  • 13
9
public function run()
{
    //
    for ($i=0; $i < 1000; $i++) { 
         DB::table('seo_contents')->insert([
            'title' => str_random(10),
            'content' => str_random(100),
            'created_at'=>date('Y-m-d H:i:s'),
            'updated_at'=>date('Y-m-d H:i:s'),

        ]);
    }

}
Simple Test
  • 157
  • 1
  • 4
  • Never use a foreach or for loop on seeders. It's a huge performance impact if you have a lot of data. For every insert there is a query instead of doing the insert in 1 query – lewis4u Nov 20 '21 at 09:39
  • can you plz elaborate on how the dummy data generation process impact and especially the foreach or for loop? Do you have any alternative? – Simple Test Nov 20 '21 at 18:11
  • It's just about of amount of queries that hit the database.... with that code above, you would hit the database with 1000 insert queries... better way is to create the data first (in RAM) using the foreach and then use one single query to store the data like `DB::table('seo_contents')->insert($data);` where the $data is an array of generated rows – lewis4u Nov 20 '21 at 20:12
5

use truncate

<?php

use Illuminate\Database\Seeder;
use App\User;

class UsersTableSeeder extends Seeder
{
     /**
     * Run the database seeds.
     *
     * @return void
     */

  public function run()
    {

      User::truncate();

        $users =  [
            [
              'name' => 'Super Admin',
              'email' => 'superadmin@gmail.com',
              'password' => '123456',
            ],
            [
              'name' => 'Account Admin',
              'email' => 'accountadmin@gmail.com',
              'password' => '13456',
            ],
            [
              'name' => 'Project Admin',
              'email' => 'projectadmin@gmail.com',
              'password' => '13456',
            ],
            [
              'name' => 'Client Admin',
              'email' => 'clientadmin@gmail.com',
              'password' => '13456',
            ]
          ];

          User::create($users);

    }
}
Mebrouki Amine
  • 351
  • 1
  • 4
  • 6
  • This actually works with Laravel 10 as well and I fount it the easiest solution to create multiple records with php artisan db:seed – shaz3e Apr 24 '23 at 10:07
3

If anyone is struggling with this, I have been using the following since Laravel 5 and can confirm is still working in Laravel 7+...

class UserTableSeeder extends Seeder {

public function run()
{
    \DB::table('users')->delete();

    \DB::table('users')->insert(array (
        0 => 
          array (
                 'id' => 1,
                 'name' => 'Stephan de Vries',
                 'username' => 'stephan',
                 'email' => 'stephan-v@gmail.com',
                 'password' => bcrypt('carrotz124'
         ),
        1 => 
          array (
                 'id' => 2,
                 'name' => 'John doe',
                 'username' => 'johnny',
                 'email' => 'johndoe@gmail.com',
                 'password' => bcrypt('carrotz1243'
         ),
     ));

}}
DCL_Dev
  • 97
  • 10
0

I am doing in this way to insert new and update the previous records everytime seeder runs.

$languages = [
        ['id' => 1, 'language_name' => 'English', 'language_code' => 'en'],
        ['id' => 2, 'language_name' => 'Spanish', 'language_code' => 'es'],
        ['id' => 3, 'language_name' => 'French', 'language_code' => 'fr'],
        ['id' => 4, 'language_name' => 'German', 'language_code' => 'de'],
        ['id' => 5, 'language_name' => 'Swahili', 'language_code' => 'sw']
    ];

    foreach ($languages as $language) {
        Language::updateOrCreate(['id' => $language['id']], $language);
    }
Tech Leadz
  • 49
  • 4
0

You can use a for loop if you are trying to insert a random data for staging

for ($i = 0; $i <= 29; $i++) {
            DB::table('userdata')->insert([
                'uname' => Str::random(10),
                'upassword' => Str::random(10)
            ]);

            DB::table('testtable2')->insert([
                'name' => Str::random(10),
                'number' => random_int(100, 9999)
            ]);
     }
ni9khil
  • 1
  • 5