【问题标题】:Insert data to a pivot table in laravel在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(); 这些句子的地方应该被替换。谢谢
  • 我添加了一个答案,进一步解释了我的评论并包含您自己的更正。

标签: php laravel eloquent pivot-table


【解决方案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 个标签时在我的下拉列表中”,这表明它是一个类似数组的输入。也就是说,我想我们不应该假设。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 2020-09-19
      • 2018-06-15
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      相关资源
      最近更新 更多