【问题标题】:Update pivot column values更新数据透视列值
【发布时间】:2016-12-03 12:02:50
【问题描述】:

为了论证,虽然关系是 one2many(一棵树有鸟),让我们检查想象的 many2many 示例来描述问题。

我有一个数据透视表,表示栖息在树上的鸟 每只鸟都有一个索引,表示树上鸟的顺序,这意味着独特的三重奏$table->unique( array('index', 'tree_id', 'bird_id') )

tree_id | bird_id | index
-------- --------- -------
  ...       ...      ...
   1         3        1 
  ...       ...      ...

所以当一只新鸟落在树上时,我希望它成为树上的第一只鸟,并增加树上的休息索引。

使用 eloquent 有效地做到这一点的方法是什么?

【问题讨论】:

    标签: php mysql laravel eloquent pivot


    【解决方案1】:

    根据我的理解,树和鸟模型之间存在多对多的关系,所以你的表格应该是这样的:

    - trees
        - id
        - name
        ...
    
    - birds
        - id
        - name
        - ...
    
    - bird_tree
        - id
        - bird_id
        - tree_id
        - index
    

    你的模型应该是这样的:

    class Tree extends Model
    {
    
        public function birds()
        {
            return $this->belongsToMany(Bird::class)
                        ->withPivot('index')
                        ->withTimestamps();
        }
    
    }
    
    class Bird extends Model
    {
    
        public function trees()
        {
            return $this->belongsToMany(Tree::class)
                        ->withPivot('index')
                        ->withTimestamps();
        }
    
    }
    

    而如果您想在数据透视表bird_tree 中添加新条目,您可以使用attach() 方法,如下所示:

    $tree->birds()->attach(1, ['index' => 1]);
                           ^
         bird's id_________|
    

    如果您想更新任何行,例如,如果您想更新 bird_tree 表中任何条目的任何索引,您可以使用 updateExistingPivot() 方法: p>

    $tree->birds()->sync([$bird->id => [ 'index' => 'someValue'] ]);
    

    请参阅 Laravel 文档:

    希望这会有所帮助!

    【讨论】:

    • 10 倍抱歉延​​迟我会在测试解决方案 +1 后立即批准答案
    【解决方案2】:

    试试这个:

    // Tree.php
    
    public function perchBird($birdId)
    {
        $perched = $this->birds->pluck('id')->toArray();
        $perched = array_combine($perched, array_fill(0, count($perched), ['index' => DB::raw('`index`+1')]));
        $perched[$birdId] = ['index' => 1];
    
        $this->birds()->sync($perched);
    }
    

    分解:

    1) 获取已栖息鸟类的 ID

    $perched = $this->birds->pluck('id')->toArray();
    

    2) 使用 DB::raw 创建一个关联数组,其中栖息鸟类的 id 作为键,更新语句作为值,以便 Laravel 理解它是 MySQL 计算,而不是本身的值。这样我们就可以获取现有的索引并增加它。

    $perched = array_combine($perched, array_fill(0, count($perched), ['index' => DB::raw('`index`+1')]));
    

    3) 将新栖息的鸟添加到数组中,索引为 1。

    $perched[$birdId] = ['index' => 1];
    

    4) 触发数据透视表同步

    $this->birds()->sync($perched);
    

    值得注意的是,sync 方法将单独运行每个更新语句,这可能会令人望而却步,具体取决于您期望拥有的栖息鸟类的数量或更新它们的频率。另一种方法是执行一个原始查询来增加索引,然后再执行一个查询来栖息一只新鸟:

    public function perchBird($birdId)
    {
        DB::update('update bird_tree set `index` = (`index`+1) where tree_id = ?', [$this->id]);
        $this->birds()->attach($birdId, ['index' => 1]);
    }
    

    按照要求,不完全是 Eloquent,但仍然非常简单易读。

    【讨论】:

    • 10 倍抱歉延​​迟我会在测试解决方案 +1 后立即批准答案
    猜你喜欢
    • 2019-01-22
    • 1970-01-01
    • 2015-08-12
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    相关资源
    最近更新 更多