在laravel中将数据插入数据透视表

Posted

技术标签:

【中文标题】在laravel中将数据插入数据透视表【英文标题】:Insert data to a pivot table in laravel 【发布时间】:2014-08-24 04:53:45 【问题描述】:

我有 3 张桌子:poststagspost_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) 的数据透视表中,然后添加关系。如果您担心标签部分失败,然后数据库不一致,您应该使用事务。

最后,您遇到的“约定”错误是,根据定义,属于多方关系涉及结果集合。因此,tagpost 应该分别是 tagsposts

所以这是我重写的代码版本:

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 数据透视表批量插入多个字段

在数据透视表 laravel 中删除行和插入行

Laravel 在数据透视表中为克隆字段的一个关系 ID 插入多行

如何在 Laravel 中使用附加或同步方法在数据透视表中插入多个值

在 Eloquent 中将数据透视表与多个表连接起来

将价格插入数据透视表