将数据插入到 Laravel 中的数据透视表
我有 3 个表:posts
、tags
、post_tag
.
I have 3 tables: posts
, tags
, post_tag
.
每个Post
都有很多标签,所以我对它们使用 hasMany
方法.但是,当我在下拉列表中选择例如 3 个标签时,我无法将它们添加到 post_tag
,因此我无法选择和显示每个帖子的标签.
Each Post
has many tags so I use hasMany
method for them. But when I choose for example 3 tags in my dropdown list, I can't add them to post_tag
and as the result I can't select and show each post's tags.
我的发布
模型:
class Post extends Eloquent{
public function tag()
{
return $this->hasMany('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
保存到 post_tag
表及其标签 ID,但它不起作用.感谢您抽出宝贵时间.
I expect to save this post_id
save to post_tag
table with its tag ids,
but it doesn't work. Thanks for your time.
推荐答案
您的基本想法是正确的,但是您的代码存在一些问题.有些正在阻止它工作,有些只是常规问题.
You have a basic idea right, but there are a few issues with your code. Some are stopping it from working and some are just conventional issues.
首先,这是一个 belongsTomany
关系(你有一个数据透视表)所以你必须将关系的两边定义为 belongsToMany
(即使 hasMany
是您考虑其中一侧或两侧的方式).这是因为 Laravel 期望具有两种不同关系类型的特定数据库结构.
First off, this is a belongsTomany
relationship (you have a pivot table) so you must define both sides of the relationship as belongsToMany
(even if hasMany
is the way you think about one or both of the side of it). This is because Laravel expects a certain database structure with the two different relationship types.
另一个问题(您自己发现的)是您在实际保存帖子之前将标签添加到关系中(通过 ->tag()->sync()
. 你必须先保存帖子(这样 Laravel 才知道要为 post_id
添加到数据透视表中的 ID)然后添加关系.如果你担心标签部分失败然后有不一致的数据库你应该使用事务.
Another issue (that you found yourself) is that you are adding the tags to the relation (via ->tag()->sync()
before you've actually saved the post. You must first save the post (so that laravel knows what ID to add to the pivot table for post_id
) and then add the relations. If you are worried about the tags part failing and then having an inconsistent database you should use transactions.
最后,您遇到的约定"错误是多对多关系,根据定义,涉及结果集合.因此,tag
和 post
应该分别是 tags
和 posts
.
Finally, the 'convention' errors you have is that a belongs-to-many relationship, by definition, involves collections of results. As such, tag
and post
shoudl be tags
and posts
respectively.
这是我重写的代码版本:
So here's my rewritten version of your code:
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');
}
}
}
现在很多控制器代码都以事务为中心——如果你不太关心它,那么你可以删除它.此外,还有几种方法可以完成这些事务——我采用了一种并不理想但用最少的代码就可以说明问题的方法.
Now a lot of that controller code centres around the transaction stuff - if you don't care too much about that then you're all good to remove it. Also there are several ways to do that transaction stuff - I've gone with one that's not ideal but gets the point across in a minimal amount of code.
相关文章