Masseneinfügung in Laravel mit eloquentem ORM

156

Wie können wir mit Eloquent ORM Einfügungen von Massendatenbanken in Laravel durchführen?

Ich möchte dies in Laravel erreichen: https://stackoverflow.com/a/10615821/600516, aber ich erhalte die folgende Fehlermeldung.

SQLSTATE [HY093]: Ungültige Parameternummer: gemischte benannte und Positionsparameter.

Phönixzauberer
quelle
1
Haben Sie eine has_manyBeziehung zu Ihren Modellen?
PapaSmurf
1
@ Jonathandey Nein, ich habe im Moment keine Beziehungen
Phoenixwizard
@ DavidBarker Ich habe versucht, den Quesr-String mit einer for-Schleife zu bilden. Ich habe auch versucht, Transaktionen in Laravel zu verwenden.
Phoenixwizard
@AramBhusal Könnten Sie Ihren Code veröffentlichen? Ich bin sicher, ich habe hier einen Code, der Ihnen helfen wird.
David Barker

Antworten:

302

Sie können einfach verwenden Eloquent::insert().

Beispielsweise:

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

Coder::insert($data);
GTF
quelle
2
Gilt das noch für Laravel 4?
Advait
4
@advait: Ja, es gilt immer noch für Laravel 4.
Ola
37
Bemerkenswert ist, dass es Eloquenttatsächlich nicht berührt . Es wird nur der Aufruf der Query\Builder@insert()Methode als Proxy ausgeführt. Es gibt keine Möglichkeit, mehrere Zeilen mit Eloquent effizient einzufügen, und es gibt auch keine Methode für Masseneinfügungen.
Jarek Tkaczyk
6
@CanVural Was sollen wir tun, um auch Zeitstempel zu aktualisieren / zu erstellen?
Milan Maharjan
3
Dies wird einen Einsatz verwenden. Bei einem ausreichend großen Array schlägt dies fehl.
Patrox
72

Wir können die GTF-Antwort aktualisieren, um Zeitstempel einfach zu aktualisieren

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

Update: Um das Datum zu vereinfachen, können wir Kohlenstoff verwenden, wie von @Pedro Moreira vorgeschlagen

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

UPDATE2: Verwenden Sie für Laravel 5 updated_atanstelle vonmodified_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);
Eslam Salem Mahmoud
quelle
42
Oder verwenden Sie Carbon am Anfang des Skripts, um eine $nowVariable zu definieren : $now = Carbon::now('utc')->toDateTimeString();. Dann einfach 'created_at' => $now, 'updated_at' => $nowfür jede Einfügung verwenden.
Pedro Moreira
2
Wie können wir alle IDs neu eingefügter Zeilen erhalten?
Akshaykumar6
2
Warum 'utc'? Ist es die Präferenz des Projekts oder funktioniert eloquent immer in 'utc'?
Pilat
6
Ich möchte kein großes Argument "Leerzeichen gegen Tabulatoren" starten, aber bitte speichern Sie Zeitstempel in UTC! Es erspart Ihnen später eine Menge Schmerzen! Denken Sie an Benutzer weltweit :)
iSS
2
Wenn ich fragen darf, was ist der große Bedarf Carbonin dieser Situation? Was ist los mit date("Y-m-d H:i:s")?
Ifedi Okonkwo
29

Wer dies liest, sollte die createMany()Methode überprüfen .

/**
 * 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;
}
Alex
quelle
28
Dies wird nicht als Masseneinsatz bezeichnet. Aufgrund der schlechten Implementierung bereitet diese Funktion dieselbe Abfrage einmal pro Element vor und führt sie aus.
Paul Spiegel
Es ist erwähnenswert, dass dies eine Beziehungsmethode ist, die nicht direkt aus dem Modell aufgerufen werden kann, d Model::createMany(). H.
Digout
24

So machst du es auf eloquentere Weise,

    $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);
imal hasaranga perera
quelle
3

Ich habe viele Male danach gesucht und schließlich benutzerdefinierte timestampswie folgt verwendet:

$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],
    ..................................
]);
srmilon
quelle
2

Eloquent::insert ist die richtige Lösung, aktualisiert jedoch nicht die Zeitstempel, sodass Sie wie folgt vorgehen können

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

Die Idee ist, Create_at und Updated_at zum gesamten Array hinzuzufügen, bevor Sie das Einfügen durchführen

sumit
quelle
0

Ab Laravel 5.7 Illuminate\Database\Query\Builderkönnen Sie die Methode insertUsing verwenden.

$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));
Walid Natat
quelle
-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));

UserSubscriptionist mein Modellname. Dies gibt "true" zurück, wenn das Einfügen erfolgreich ist, andernfalls "false".

Nikunj K.
quelle
-1

Ein Laravel-Weg, um dieses Problem zu lösen, besteht möglicherweise darin, eine Sammlung zu verwenden und sie in einer Schleife einzufügen, wobei das Modell die Zeitstempel nutzt.

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

BEARBEITEN:

Entschuldigung für mein Missverständnis. Für das Masseneinfügen könnte dies helfen, und vielleicht können Sie damit gute Sämaschinen herstellen und sie ein wenig optimieren.

<?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);
    }
}
Francisco Daniel
quelle
1
Dies führt eine Abfrage pro Element durch. Es ist keine Masseneinfügung.
Emile Bergeron
1
@ EmileBergeron Ich stimme dir zu. Ich habe meinen Beitrag bearbeitet, sodass dies möglicherweise zu einer guten Masseneinfügung beitragen kann. Wenn Sie die Aufgaben, die viel Zeit in Anspruch nehmen (Carbon, bcrypt), verlassen, können Sie viel Zeit sparen.
Francisco Daniel
-1

Beim Einfügen von Kategoriebeziehungen stieß ich auf dasselbe Problem und hatte keine Ahnung, außer dass ich in meinem beredten Modell Self () verwendet habe, um eine Instanz derselben Klasse in foreach zu haben, um mehrere Speicherungen aufzuzeichnen und IDs abzurufen.

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

ohne "$ obj = new Self ()" werden nur einzelne Datensätze gespeichert (wenn $ obj $ this war)

justnajm
quelle
-4

Problem gelöst ... Tabelle für Migration ändern

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

Lösung:

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