在laravel中将数据插入数据透视表
Posted
技术标签:
【中文标题】在laravel中将数据插入数据透视表【英文标题】:Insert data to a pivot table in laravel 【发布时间】:2014-08-24 04:53:45 【问题描述】:我有 3 张桌子:posts
、tags
、post_tag
。
每个Post
都有很多标签,所以我对它们使用hasMany
方法。但是当我在下拉列表中选择例如 3 个标签时,我无法将它们添加到 post_tag
,因此我无法选择并显示每个帖子的标签。
我的Post
模特:
class Post extends Eloquent
public function tag()
return $this->hasMany('Tag');
我的Tag
模特:
class Tag extends Eloquent
public function post()
return $this->belongsToMany('Post');
还有我的postController
:
class postController extends BaseController
public function addPost()
$post=new Post;
$post_title=Input::get('post_title');
$post_content=Input::get('post_content');
$tag_id=Input::get('tag');
$post->tag()->sync($tag_id);
$post->save();
我希望将这个 post_id
保存到带有标签 ID 的 post_tag
表中,
但它不起作用。感谢您的宝贵时间。
【问题讨论】:
如果一个关系有一个数据透视表,那么它的两边都应该是belongsToMany
。此外,您应该真正将方法命名为 tags
而不是 tag
,因为它是 *Many 关系。
@alexrussell 是的,你是对的 :)。其他问题是$post->tag()->sync($tag_id); $post->save();
这些句子的地方应该被替换。谢谢
我添加了一个答案,进一步解释了我的评论并包含您自己的更正。
【参考方案1】:
您的基本想法是对的,但是您的代码存在一些问题。有些会阻止它工作,有些只是常规问题。
首先,这是一个belongsTomany
关系(您有一个数据透视表),因此您必须将关系的双方定义为belongsToMany
(即使hasMany
是您考虑其中一个或两个的方式一边)。这是因为 Laravel 期望具有两种不同关系类型的特定数据库结构。
另一个问题(您自己发现)是您正在将标签添加到关系中(在您实际保存帖子之前通过->tag()->sync()
。您必须先保存帖子(以便 laravel 知道要添加什么 ID到post_id
) 的数据透视表中,然后添加关系。如果您担心标签部分失败,然后数据库不一致,您应该使用事务。
最后,您遇到的“约定”错误是,根据定义,属于多方关系涉及结果集合。因此,tag
和 post
应该分别是 tags
和 posts
。
所以这是我重写的代码版本:
class Post extends Eloquent
public function tags()
return $this->belongsToMany('Tag');
class Tag extends Eloquent
public function posts()
return $this->belongsToMany('Post');
class PostController extends BaseController
public function addPost()
// assume it won't work
$success = false;
DB::beginTransaction();
try
$post = new Post;
// maybe some validation here...
$post->title = Input::get('post_title');
$post->content = Input::get('post_content');
if ($post->save())
$tag_ids = Input::get('tags');
$post->tags()->sync($tag_ids);
$success = true;
catch (\Exception $e)
// maybe log this exception, but basically it's just here so we can rollback if we get a surprise
if ($success)
DB::commit();
return Redirect::back()->withSuccessMessage('Post saved');
else
DB::rollback();
return Redirect::back()->withErrorMessage('Something went wrong');
现在很多控制器代码都围绕着事务处理——如果你不太关心这些,那么你可以删除它。还有几种方法可以处理事务 - 我选择了一种不太理想的方法,但用最少的代码就能理解这一点。
【讨论】:
【参考方案2】:要将数据插入数据透视表名称diplome_user,只需按照我的示例:我的数据透视表看起来像:
//this is Diplome Model
class Diplome extends Model
public function users()
return $this->belongsToMany('App\User','diplome_user')->withPivot('etablissement', 'annee', 'mention');;
现在在我的 DiplomeController 中,我可以进行以下查询:
$user = Auth::user();
因为我需要一个用户,所以我只取连接的用户,之后,我创建一个 Diplome 实例,例如:
$diplome = new Diplome();
$diplome->libelle = "the name";
$diplome->decription= "description of the ...";
$diplome->save();
现在最重要的一步是:
$diplome->users()->attach($user, ['etablissement'=> 'bib',
'annee'=>'2015',
'mention'=>'AB',
]);
结果如下:
【讨论】:
【参考方案3】:sync()
方法需要一个数组。如果您只是将标签 ID 放在一个内,它应该可以工作,如下所示:
$post->tag()->sync([$tag_id]);
【讨论】:
Call to undefined method Illuminate\Database\Query\Builder::sync()
。它总是出现:(
@joelhinz 据我所知,上面的代码确实会发送一个数组-$tag_id
来自Input::get('tag')
,在介绍中,OP 说“当我选择例如 3 个标签时在我的下拉列表中”,这表明它是一个类似数组的输入。也就是说,我想我们不应该假设。以上是关于在laravel中将数据插入数据透视表的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 在数据透视表中为克隆字段的一个关系 ID 插入多行