我们如何使用 Eloquent ORM 在 Laravel 中执行批量数据库插入?
我正在处理一个 XML 文档,循环遍历它的元素。我想在 Laravel 中完成这样的事情:
$sXML = download_page('http://remotepage.php&function=getItems&count=100&page=1');
$oXML = new SimpleXMLElement($sXML);
$query = "INSERT INTO tbl_item (first_name, last_name, date_added) VALUES";
foreach($oXML->results->item->item as $oEntry){
$query .= "('" . $oEntry->firstname . "', '" . $oEntry->lastname . "', '" . date("Y-m-d H:i:s") . "'),";
}
mysql_query($query);
但我收到以下错误。
SQLSTATE[HY093]:无效参数号:混合命名参数和位置参数。
has_many
关系?
您可以只使用 Eloquent::insert()
。
例如:
$data = [
['name'=>'Coder 1', 'rep'=>'4096'],
['name'=>'Coder 2', 'rep'=>'2048'],
//...
];
Coder::insert($data);
我们可以更新 GTF 答案以轻松更新时间戳
$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);
更新:为了简化日期,我们可以按照@Pedro Moreira 的建议使用碳
$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:对于 laravel 5 ,使用 updated_at
而不是 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);
$now
变量:$now = Carbon::now('utc')->toDateTimeString();
。然后每次插入只需使用 'created_at' => $now, 'updated_at' => $now
。
Carbon
的最大需求是什么? date("Y-m-d H:i:s")
有什么问题?
这就是你如何以更雄辩的方式做到这一点,
$allinterests = [];
foreach($interests as $item){ // $interests array contains input data
$interestcat = new User_Category();
$interestcat->memberid = $item->memberid;
$interestcat->catid = $item->catid;
$allinterests[] = $interestcat->attributesToArray();
}
User_Category::insert($allinterests);
对于正在阅读本文的人,请查看 createMany()
method。
/**
* 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;
}
Model::createMany()
中调用。
我搜索了很多次,最后使用了自定义timestamps
,如下所示:
$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],
..................................
]);
Eloquent::insert
是正确的解决方案,但它不会更新时间戳,因此您可以执行以下操作
$json_array=array_map(function ($a) {
return array_merge($a,['created_at'=>
Carbon::now(),'updated_at'=> Carbon::now()]
);
}, $json_array);
Model::insert($json_array);
这个想法是在插入之前在整个数组上添加 created_at 和 updated_at
$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));
UserSubscription
是我的型号名称。如果插入成功,则返回“true”,否则返回“false”。
也许解决这个问题的更 Laravel 方法是使用一个集合并将其循环插入模型中,利用时间戳。
<?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);
});
}
}
编辑:
对不起,我的误解。对于批量插入,这可能会有所帮助,也许您可以制作好的播种机并对其进行一些优化。
<?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);
}
}
从带有 Illuminate\Database\Query\Builder
的 Laravel 5.7 开始,您可以使用 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));
对于类别关系插入,我遇到了同样的问题并且不知道,除了在我雄辩的模型中,我使用 Self() 在 foreach 中有一个相同类的实例来记录多个保存和抓取 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();
}
}
没有 "$obj = new Self()" 它只保存一条记录(当 $obj 是 $this 时)
问题已解决... 更改表以进行迁移
$table->timestamp('created_at')->nullable()->useCurrent();
解决方案:
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();
});
不定期副业成功案例分享
Eloquent
。它只是代理对Query\Builder@insert()
方法的调用。没有办法使用 Eloquent 有效地插入多行,也没有提供任何批量插入的方法。