Chèn số lượng lớn vào Laravel bằng ORM hùng hồn


156

Làm cách nào chúng tôi có thể thực hiện chèn cơ sở dữ liệu hàng loạt trong Laravel bằng Eloquent ORM?

Tôi muốn thực hiện điều này trong Laravel: https://stackoverflow.com/a/10615821/600516 nhưng tôi gặp lỗi sau.

SQLSTATE [HY093]: Số tham số không hợp lệ: hỗn hợp có tên và tham số vị trí.


1
Bạn có một has_manymối quan hệ trên các mô hình của bạn?
PapaSmurf

1
@jonathandey không tôi không có bất kỳ mối quan hệ nào vào lúc này
phoenixwizard

@DavidBarker tôi đã thử tạo chuỗi quesr bằng vòng lặp for. Tôi cũng đã thử sử dụng các giao dịch trong laravel.
phượng hoàng

@AramBhusal Bạn có thể đăng mã của mình không? Tôi chắc chắn rằng tôi có một số mã ở đây sẽ giúp bạn.
David Barker

Câu trả lời:


302

Bạn chỉ có thể sử dụng Eloquent::insert().

Ví dụ:

$data = array(
    array('name'=>'Coder 1', 'rep'=>'4096'),
    array('name'=>'Coder 2', 'rep'=>'2048'),
    //...
);

Coder::insert($data);

2
Điều này vẫn áp dụng cho Laravel 4?
ủng hộ

4
@advait: có, nó vẫn áp dụng cho Laravel 4.
Ola

37
Đáng chú ý là nó không chạm Eloquentvào trong thực tế. Nó chỉ ủy nhiệm cuộc gọi đến Query\Builder@insert()phương thức. Không có cách nào để chèn nhiều hàng một cách hiệu quả với Eloquent, cũng như không cung cấp bất kỳ phương thức nào để chèn số lượng lớn.
Jarek Tkachot

6
@CanVural chúng ta nên làm gì để cập nhật / tạo dấu thời gian?
Milan Maharjan

3
Điều này sẽ sử dụng một chèn. Vì vậy, đưa ra một mảng đủ lớn, nó sẽ thất bại.
patrox

72

Chúng tôi có thể cập nhật câu trả lời GTF để cập nhật dấu thời gian một cách dễ dàng

$data = array(
    array(
        'name'=>'Coder 1', 'rep'=>'4096',
        'created_at'=>date('Y-m-d H:i:s'),
        'modified_at'=> date('Y-m-d H:i:s')
       ),
    array(
         'name'=>'Coder 2', 'rep'=>'2048',
         'created_at'=>date('Y-m-d H:i:s'),
         'modified_at'=> date('Y-m-d H:i:s')
       ),
    //...
);

Coder::insert($data);

Cập nhật: để đơn giản hóa ngày chúng ta có thể sử dụng carbon như @Pedro Moreira đề xuất

$now = Carbon::now('utc')->toDateTimeString();
$data = array(
    array(
        'name'=>'Coder 1', 'rep'=>'4096',
        'created_at'=> $now,
        'modified_at'=> $now
       ),
    array(
         'name'=>'Coder 2', 'rep'=>'2048',
         'created_at'=> $now,
         'modified_at'=> $now
       ),
    //...
);

Coder::insert($data);

CẬP NHẬT2: cho laravel 5, sử dụng updated_atthay vìmodified_at

$now = Carbon::now('utc')->toDateTimeString();
$data = array(
    array(
        'name'=>'Coder 1', 'rep'=>'4096',
        'created_at'=> $now,
        'updated_at'=> $now
       ),
    array(
         'name'=>'Coder 2', 'rep'=>'2048',
         'created_at'=> $now,
         'updated_at'=> $now
       ),
    //...
);

Coder::insert($data);

42
Hoặc sử dụng Carbon ở đầu tập lệnh để xác định một $nowbiến : $now = Carbon::now('utc')->toDateTimeString();. Sau đó chỉ cần sử dụng 'created_at' => $now, 'updated_at' => $nowcho mỗi lần chèn.
Pedro Moreira

2
Làm thế nào chúng ta có thể nhận được tất cả ID của các hàng mới được chèn?
akshaykumar6

2
Tại sao 'utc'? Đó có phải là ưu tiên của dự án, hay, liệu tài hùng biện luôn hoạt động trong 'utc'?
pilat

6
Tôi không muốn bắt đầu một đối số "khoảng trắng so với tab" lớn, nhưng làm ơn, hãy lưu dấu thời gian trong UTC! Nó sẽ giúp bạn tiết kiệm rất nhiều nỗi đau sau này! Hãy suy nghĩ về người dùng trên toàn cầu :)
iSS

2
Nếu tôi có thể hỏi, nhu cầu lớn Carbontrong tình huống này là gì? Có chuyện gì với bạn date("Y-m-d H:i:s")vậy?
Ifedi Okonkwo

30

Đối với bất cứ ai đang đọc này, kiểm tra createMany()phương pháp .

/**
 * Create a Collection of new instances of the related model.
 *
 * @param  array  $records
 * @return \Illuminate\Database\Eloquent\Collection
 */
public function createMany(array $records)
{
    $instances = $this->related->newCollection();

    foreach ($records as $record) {
        $instances->push($this->create($record));
    }

    return $instances;
}

28
Đây không phải là những gì được gọi là chèn số lượng lớn. Do triển khai kém, chức năng này sẽ chuẩn bị và thực hiện cùng một truy vấn một lần cho mỗi Mục.
Paul Spiegel

Đáng chú ý đây là một phương thức quan hệ, không thể gọi trực tiếp từ mô hình tức là Model::createMany().
đào

24

Đây là cách bạn làm điều đó theo cách hiệu quả hơn,

    $allintests = [];
    foreach($intersts as $item){ //$intersts array contains input data
        $intestcat = new User_Category();
        $intestcat->memberid = $item->memberid;
        $intestcat->catid= $item->catid;
        $allintests[] = $intestcat->attributesToArray();
    }
    User_Category::insert($allintests);

3

Tôi đã tìm kiếm nhiều lần cho nó, cuối cùng đã sử dụng tùy chỉnh timestampsnhư dưới đây:

$now = Carbon::now()->toDateTimeString();
Model::insert([
    ['name'=>'Foo', 'created_at'=>$now, 'updated_at'=>$now],
    ['name'=>'Bar', 'created_at'=>$now, 'updated_at'=>$now],
    ['name'=>'Baz', 'created_at'=>$now, 'updated_at'=>$now],
    ..................................
]);

2

Eloquent::insert là giải pháp phù hợp nhưng nó sẽ không cập nhật dấu thời gian, vì vậy bạn có thể làm một cái gì đó như dưới đây

 $json_array=array_map(function ($a) { 
                        return array_merge($a,['created_at'=> 
                                            Carbon::now(),'updated_at'=> Carbon::now()]
                                           ); 
                                     }, $json_array); 
 Model::insert($json_array);

Ý tưởng là thêm created_at và update_at trên toàn bộ mảng trước khi thực hiện thao tác chèn


0

Từ Laravel 5.7 với Illuminate\Database\Query\Builderbạn có thể sử dụng phương thức insertUsing.

$query = [];
foreach($oXML->results->item->item as $oEntry){
    $date = date("Y-m-d H:i:s")
    $query[] = "('{$oEntry->firstname}', '{$oEntry->lastname}', '{$date}')";
}

Builder::insertUsing(['first_name', 'last_name', 'date_added'], implode(', ', $query));

-1
$start_date = date('Y-m-d h:m:s');        
        $end_date = date('Y-m-d h:m:s', strtotime($start_date . "+".$userSubscription['duration']." months") );
        $user_subscription_array = array(
          array(
            'user_id' => $request->input('user_id'),
            'user_subscription_plan_id' => $request->input('subscription_plan_id'),
            'name' => $userSubscription['name'],
            'description' => $userSubscription['description'],
            'duration' => $userSubscription['duration'],
            'start_datetime' => $start_date,
            'end_datetime' => $end_date,
            'amount' => $userSubscription['amount'],
            'invoice_id' => '',
            'transection_datetime' => '',
            'created_by' => '1',
            'status_id' => '1', ),
array(
            'user_id' => $request->input('user_id'),
            'user_subscription_plan_id' => $request->input('subscription_plan_id'),
            'name' => $userSubscription['name'],
            'description' => $userSubscription['description'],
            'duration' => $userSubscription['duration'],
            'start_datetime' => $start_date,
            'end_datetime' => $end_date,
            'amount' => $userSubscription['amount'],
            'invoice_id' => '',
            'transection_datetime' => '',
            'created_by' => '1',
            'status_id' => '1', )
        );
        dd(UserSubscription::insert($user_subscription_array));

UserSubscriptionlà tên mô hình của tôi. Điều này sẽ trả về "true" nếu chèn thành công "false" khác.


-1

Có lẽ một cách khác để giải quyết vấn đề này là sử dụng một bộ sưu tập và lặp nó với mô hình lợi dụng dấu thời gian.

<?php

use App\Continent;
use Illuminate\Database\Seeder;

class InitialSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        collect([
            ['name' => 'América'],
            ['name' => 'África'],
            ['name' => 'Europa'],
            ['name' => 'Asia'],
            ['name' => 'Oceanía'],
        ])->each(function ($item, $key) {
            Continent::forceCreate($item);
        });
    }
}

BIÊN TẬP:

Xin lỗi vì sự hiểu nhầm của tôi. Để chèn số lượng lớn, điều này có thể giúp ích và có thể với điều này, bạn có thể tạo ra các trình gieo hạt tốt và tối ưu hóa chúng một chút.

<?php

use App\Continent;
use Carbon\Carbon;
use Illuminate\Database\Seeder;

class InitialSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $timestamp = Carbon::now();
        $password = bcrypt('secret');

        $continents = [
            [
                'name' => 'América'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'África'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'Europa'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'Asia'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'Oceanía'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
        ];

        Continent::insert($continents);
    }
}

1
Điều này làm cho một truy vấn cho mỗi mục. Đây không phải là một số lượng lớn.
Emile Bergeron

1
@EmileBergeron Tôi đồng ý với bạn. Tôi đã chỉnh sửa bài viết của mình để có thể điều này có thể giúp chèn số lượng lớn tốt. Xem xét để lại các nhiệm vụ mất nhiều thời gian ra khỏi vòng lặp (carbon, bcrypt) điều này có thể giúp bạn tiết kiệm rất nhiều thời gian.
Francisco Daniel

-1

Đối với việc chèn quan hệ thể loại, tôi đã gặp một vấn đề tương tự và không có ý kiến ​​gì, ngoại trừ trong mô hình hùng hồn của tôi, tôi đã sử dụng Self () để có một ví dụ của cùng một lớp trong foreach để ghi lại nhiều lưu và lấy id.

foreach($arCategories as $v)
{                
    if($v>0){
        $obj = new Self(); // this is to have new instance of own
        $obj->page_id = $page_id;
        $obj->category_id = $v;
        $obj->save();
    }
}

không có "$ obj = new Self ()", nó chỉ lưu bản ghi duy nhất (khi $ obj là $ this)


-4

Vấn đề đã được giải quyết ... Thay đổi bảng để di chuyển

$table->timestamp('created_at')->nullable()->useCurrent();

Giải pháp:

Schema::create('spider_news', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('source')->nullable();
    $table->string('title')->nullable();
    $table->string('description')->nullable();
    $table->string('daterss')->nullable();

    $table->timestamp('created_at')->useCurrent();
    $table->timestamp('updated_at')->useCurrent();
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.