【问题标题】:Laravel Eloquent ORM - Many to Many Delete Pivot Table Values left overLaravel Eloquent ORM - 多对多删除数据透视表剩余值
【发布时间】:2015-02-04 11:43:38
【问题描述】:

使用 Laravel,我有以下代码

$review = Review::find(1);
$review->delete();

Review 具有使用Product 实体定义的多对多关系。当我删除评论时,我希望它会从数据透视表中的相关产品中分离出来,但事实并非如此。当我运行上面的代码时,我仍然在数据透视表中看到链接行。

我是否遗漏了一些东西,或者这就是 Laravel 的工作方式?我知道detach() 方法,但我认为删除实体也会自动将其与任何相关实体分离。

Review 是这样定义的:

<?php
class Review extends Eloquent
{
    public function products()
    {
        return $this->belongsToMany('Product');
    }
}

Product 是这样定义的:

<?php
class Product extends Eloquent
{
    public function reviews()
    {
        return $this->belongsToMany('Review');
    }
}

提前致谢。

【问题讨论】:

  • 这就是Eloquent 的工作原理。您可以将 DB 事件用于数据透视表 (@​​987654331@) 或使用 Eloquent 实现事件处理程序。类似stackoverflow.com/a/14174356/784588

标签: laravel orm many-to-many eloquent


【解决方案1】:

detach 方法用于从数据透视表中释放关系,而 delete 将删除模型记录本身,即评论表中的记录。我的理解是删除不会隐式触发分离。不过,您可以使用model events 来触发数据透视表的清理,使用类似:

Review::deleting(function($review)
{
    $review->product()->detach()
}

另外,我建议这种关系是一对多的,因为一个产品会有很多评论,但一个评论不属于很多产品(通常)。

class Review extends \Eloquent {
    public function product()
    {
        return $this->belongsTo('Product');
    }
}

class Product extends \Eloquent {
    public function reviews()
    {
        return $this->hasMany('Review');
    }
}

当然,这需要您调整数据库结构。如果您想保留数据库结构和当前关系,另一种选择是在数据透视表上应用外键约束,这样当删除评论或产品时,您可以级联删除数据透视表。

// Part of a database migration
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('review_id')->references('id')->on('reviews')->onDelete('cascade');

编辑:在添加约束时,您将清理工作推送到数据库中,而不必担心在代码中处理它。

【讨论】:

  • 在您的第一件作品中,您不会遍历结果,而只需调用 $model-&gt;relation()-&gt;detach() 这将删除单个查询中给定 $model 的所有枢轴关联。
  • 非常感谢。这彻底回答了我的问题。顺便说一句,我有一个多对多的关系,因为我有一个现有的产品评论列表,并且有些人已经在一件中评论了多个产品。
  • 如果包含 detach() 语法和要分离的项目 ID 以及指向 detach functionexample 的链接,那就太棒了
  • FK 约束在这两种方法中要好得多,恕我直言。让数据库处理一切。
  • "在数据透视表上应用外键约束,这样当评论或产品被删除时,您可以在数据透视表上级联删除。"最后一部分正是 a 在另一个问题中寻找但找不到的内容,谢谢。
【解决方案2】:

更简单的步骤:

在这个例子中,Account 有很多 Tags

要删除标签,然后帐户执行以下操作:

// delete the relationships with Tags (Pivot table) first.
$account->find($this->accountId)->tags()->detach();

// delete the record from the account table.
$account->delete($this->accountId);

在数据透视表上确保您有 ->onDelete('cascade');

$table->integer('account_id')->unsigned()->index();
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');

$table->integer('tag_id')->unsigned()->index();
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');

【讨论】:

    【解决方案3】:

    $review-&gt;product()-&gt;sync([]) 也可以。

    但是$review-&gt;product()-&gt;detach() 更明确。

    【讨论】:

      【解决方案4】:
      public function destroy($id)
      {    
          $review = Review::find($id);
          $review ->tagged_users()->detach();
          return $review ->delete(); 
      }
      

      也可以

      【讨论】:

        【解决方案5】:

        如果这种方式不能解决您的问题,您可以使用 DB 选项删除数据透视表记录,如下所示;

        DB::table('any_pivot_table')->where('x_column', $xParameter)->delete();
        

        你可以这样解决问题。

        享受您的编码!

        【讨论】:

          【解决方案6】:

          我猜你的模型关系概念有误,产品有很多评论,但评论与一个产品相关,所以你在这里有一对多的关系。 但总的来说,一般情况下的答案是:

          $product->reviews()->sync([]);
          

          【讨论】:

          • 此答案将删除产品所有评论的所有数据透视表行(假设关系确实是多对多,在这种情况下似乎有点奇怪)。它将保持产品及其评论完好无损,但不会链接。知道这是一件好事和有用的事情,但根本不能解决这个问题。
          猜你喜欢
          • 2023-02-05
          • 2014-12-13
          • 1970-01-01
          • 2015-02-11
          • 2014-12-07
          • 1970-01-01
          • 1970-01-01
          • 2017-04-11
          • 1970-01-01
          相关资源
          最近更新 更多