laravel 如何强制laravel在sync()方法中进行批量(多个)插入?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13433977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can i force laravel to do batch(multiple) insert in sync() method?
提问by warmspringwinds
When i use sync()
method laravel do a lot of separate insert queries in my intermediate table like this:
当我使用sync()
laravel 方法在我的中间表中执行很多单独的插入查询时,如下所示:
INSERT INTO `tag_user` (`user_id`, `tag_id`) VALUES ('59', '60')
INSERT INTO `tag_user` (`user_id`, `tag_id`) VALUES ('59', '61')
I want it to do one multiple insert like this:
我希望它像这样进行一次多次插入:
INSERT INTO `tag_user` (`user_id`, `tag_id`) VALUES ('59', '60'), ('59', '61')
Is it possible? I'm using MySql. It would be nice to have attach()
method that will accept array as detach()
method do. Did someone do this?
是否可以?我正在使用 MySql。拥有attach()
像detach()
方法一样接受数组的方法会很好。有人这样做过吗?
采纳答案by warmspringwinds
This is how i solved it:
我是这样解决的:
My models
我的模特
In my application each user has many tags(many to many realationship). It's called toxidatabase schema. My user table is called 'users', tags table is called 'tags'. And intermediate table is called 'tag_user' that has 'tag_id' and 'user_id' columns.
在我的应用程序中,每个用户都有许多标签(多对多关系)。它被称为toxi数据库模式。我的用户表称为“用户”,标签表称为“标签”。中间表称为“tag_user”,具有“tag_id”和“user_id”列。
User model:
用户模型:
class User extends \Eloquent
{
public static $timestamps = false;
public function tags()
{
return $this->has_many_and_belongs_to('Models\Tag');
}
}
Tag model:
标签型号:
class Tag extends \Eloquent
{
public static $timestamps = false;
}
How i replaced sync()
method
我如何替换sync()
方法
This is how i forced laravel to do sync()
method using multiple insert:
这就是我强迫 Laravelsync()
使用多个插入执行方法的方式:
//$currentUser is a model loaded from database
//Like this: $currentUser = Auth::user();
$newLinks = array();
$idsToSync = array();
foreach ($tags as $tag)
{
array_push($idsToSync, $tag->id);
}
//$currentUser->tags()->sync($idsToSync);
$currentIds = $currentUser->tags()->pivot()->lists('tag_id');
$idsToAttach = array_diff($idsToSync, $currentIds);
foreach ($idsToAttach as $value)
{
$newLink = array(
'user_id' => $currentUser->id,
'tag_id' => $value
);
$newLinks[] = $newLink;
}
if (count($newLinks) > 0)
{
\DB::table('tag_user')->insert($newLinks);
}
$idsToDetach = array_diff($currentIds, $idsToSync);
if (count($idsToDetach) > 0)
{
$currentUser->tags()->detach($idsToDetach);
}
This code does one multiple insert instead of many single ones.
此代码执行一次多次插入而不是多次插入。
回答by devric
Ya, i was working on the same thing few days back,
是的,几天前我也在做同样的事情,
eloquent does multiple insert in one sql.
eloquent 在一个 sql 中进行多次插入。
but make sure all loops are equal columns and fields, i was trying to remove the one that does not have value the first time, and mysql wont work...
但要确保所有循环都是相等的列和字段,我试图删除第一次没有价值的循环,而 mysql 将无法工作...
eg:
例如:
array(
array('name' => 'blah'),
array('name' => 'blah')
)
User::insert($data)
but if you want to update existing records than you need to do raw query.
但是如果你想更新现有记录,那么你需要做原始查询。
eg:
例如:
$keyString = '("';
$valString = '("';
foreach ($blah as $k => $v) {
$keyString .= $k . '", '
}
the goal is to return something like this
目标是返回这样的东西
$keyString // (name, email, bla, bla)
$valString // ('john doe', '[email protected]', 'bla', 'bla'), ('someone', '[email protected]', 'bla', 'bla'),
than
比
DB::query( 'replace into users' . $keyString . ' values ' . $valString );
make sure you use array count to do a check whether is the last array for comma or not
确保您使用数组计数来检查是否是逗号的最后一个数组
eg:
例如:
(++counter === count ? '),' : ')' ;
this need to refactored
这需要重构
回答by czt
A workaround would be to use Laravel's DB::transaction()
and put the sync in it as a closure.
一种解决方法是使用 LaravelDB::transaction()
并将同步作为闭包放入其中。