Etkili ORM kullanarak Laravel'e Toplu Ekleme


156

Eloquent ORM kullanarak Laravel'de toplu veritabanı eklemelerini nasıl yapabiliriz?

Bunu Laravel'de yapmak istiyorum: https://stackoverflow.com/a/10615821/600516 ama aşağıdaki hatayı alıyorum.

SQLSTATE [HY093]: Geçersiz parametre numarası: karışık adlandırılmış ve konumsal parametreler.


1
has_manyModellerinizle bir ilişkiniz var mı?
PapaSmurf

1
@jonathandey hayır ben an herhangi ilişkiler daha dont
phoenixwizard

@ DavidBarker bir for döngüsü kullanarak quesr dize oluşturmayı denedim. Laravel'de de işlemleri kullanmayı denedim.
phoenixwizard

@AramBhusal Kodunuzu kaydedebilir misiniz? Eminim burada size yardımcı olacak bazı kodlarım var.
David Barker

Yanıtlar:


302

Sadece kullanabilirsiniz Eloquent::insert().

Örneğin:

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

Coder::insert($data);

2
Bu hala Laravel 4 için geçerli mi?
advait

4
@advait: evet, hala Laravel 4 için geçerlidir
Ola

37
EloquentAslında dokunmadığını belirtmeye değer . Sadece Query\Builder@insert()yöntem çağrısına vekalet eder . Eloquent ile birden çok satırı verimli bir şekilde eklemenin bir yolu yoktur ve toplu ekler için herhangi bir yöntem sunmaz.
Jarek Tkaczyk

6
@ CanVural zaman damgalarını güncellemek / oluşturmak için ne yapmalıyız?
Milan Maharjan

3
Bu bir ek kullanır. Yani, yeterince büyük bir dizi verildiğinde başarısız olur.
patrox

72

Zaman damgalarını kolayca güncellemek için GTF yanıtını güncelleyebiliriz

$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);

Güncelleme: @Pedro Moreira'un önerdiği gibi karbonu kullanabileceğimiz tarihi basitleştirmek için

$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);

GÜNCELLEME2: laravel 5 için, updated_atyerinemodified_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
Ya da tanımlamak için komut başında Carbon kullanmak $nowdeğişkeni: $now = Carbon::now('utc')->toDateTimeString();. Sonra 'created_at' => $now, 'updated_at' => $nowher ekleme için kullanın .
Pedro Moreira

2
Yeni eklenen satırların tüm kimliklerini nasıl alabiliriz?
akshaykumar6

2
Neden 'utc'? Projenin tercihi mi, yoksa anlamlı her zaman 'utc' da mı çalışır?
17'de pilat

6
Çok büyük bir "boşluklara karşı sekmeler" argümanı başlatmak istemiyorum, ancak lütfen UTC'de zaman damgalarını kaydedin! Daha sonra size büyük miktarda acı kazandıracak! Küresel olarak kullanıcıları düşünün :)
iSS

2
Eğer sorabilirsem, Carbonbu durumda en büyük ihtiyaç nedir? Sorun nedir date("Y-m-d H:i:s")?
Ifedi Okonkwo

30

Bunu kim okuyorsa, createMany()yönteme bakın .

/**
 * 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
Bu, toplu ekleme adı verilen şey değildir. Kötü uygulama nedeniyle, bu işlev her öğe için aynı sorguyu hazırlar ve yürütür.
Paul Spiegel

Bunun bir ilişki yöntemi olduğunu belirtmek gerekir, yani doğrudan modelden çağrılamaz Model::createMany().
digout

24

Bunu daha Verimli bir şekilde yapıyorsunuz,

    $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

Bunun için birçok kez aradım, sonunda timestampsaşağıdaki gibi özel kullandım :

$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 doğru çözümdür ancak zaman damgalarını güncellemeyecektir, böylece aşağıdaki gibi bir şey yapabilirsiniz

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

Buradaki fikir, ekleme yapmadan önce tüm diziye create_at ve updated_at eklemektir.


0

Laravel 5.7 ile Illuminate\Database\Query\BuilderinsertUsing yöntemini kullanabilirsiniz.

$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));

UserSubscriptionbenim model adım. Ekleme başarıyla "false" olursa, "true" döndürür.


-1

Belki de bu sorunu çözmenin daha Laravel yolu, bir koleksiyon kullanmak ve zaman damgalarından yararlanan modelle ekleyerek döngü yapmaktır.

<?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);
        });
    }
}

DÜZENLE:

Yanlış anladığım için üzgünüm. Toplu yerleştirmek için bu yardımcı olabilir ve belki de bununla birlikte iyi fideler yapabilir ve biraz optimize edebilirsiniz.

<?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
Bu öğe başına bir sorgu yapar. Toplu bir ekleme değil.
Emile Bergeron

1
@EmileBergeron Sana katılıyorum. Gönderiyi düzenledim, bu yüzden belki de bu iyi toplu ekleme için yardımcı olabilir. Çok fazla zaman alan görevleri döngüden (karbon, bcrypt) bırakmak, bu size çok zaman kazandırabilir.
Francisco Daniel

-1

Kategori ilişkilerinin eklenmesi için aynı sorunla karşılaştım ve hiçbir fikrim yoktu, ancak benim sevinçli modelimde birden çok tasarruf ve not tutma kimliğini kaydetmek için foreach'te aynı sınıfın bir örneğine sahip olmak için Self () kullandım.

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();
    }
}

"$ obj = new Self ()" olmadan yalnızca tek bir kayıt kaydeder ($ obj $ $ olduğunda)


-4

Sorun çözüldü ... Taşıma için tabloyu değiştirme

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

Çözüm:

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();
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.