Laravel的hasMany解除关系

13

关于删除子模型方面,我在使用Eloquent时遇到了问题: 当在process2()中执行此操作时,仍会保留已删除的模型,这是不正确的。

模型

    namespace App\Models;

    use Illuminate\Database\Eloquent\Model;

    class Model1 extends Model
    {
        public function seasons() {
            return $this->hasMany('App\Models\Seasons', 'series_id', 'id');
        }
    }

服务

class Process {
    public function process1($model1Instance) {

        for($model1Instance->seasons() as $season) {
            if(//whatever//) {
                $season->delete();
            }
        }
    }
    public function process2($model1Instance) {
        for($model1Instance->seasons() as $season) {
            //At this point I still have the deleted instance
        }
    }
}

使用方法

$proc = new Process();
......
$proc->process1($model1Instance);
$proc->process2($model1Instance);

process1()从父级中移除一个模型时,如何在process2()中将其删除?

尝试过/将要尝试的:

1.方法: $model1Instance->seasons()->detach($season); 但遇到了问题:Call to undefined method Illuminate\Database\Query\Builder::detach()

2.另一个类 我可以创建另一个简单类来存储这些内容,但我认为这并不是好的方案,虽然我可以设置筛选后的季节,但仍需使用Model1实例:

class Model1Copy {
    private $seasons;
    public function __construct($seasons) {
        $this->seasons = $seasons;
    }
}
  1. Fatal when tried:

    public function process1($model1Instance) {

    for($model1Instance->seasons() as $season) {
        if(//whatever//) {
            $season->delete();
        } else {
        $childs[]=$season;
        }
    }
    $model1Instance->seasons = $childs
    

    }

  2. Would be to make my own repositories to skip the ORM`s behavior, but it is frustrating because I have to rewrite all queries just to remove an instance...


我猜 $season->delete() 调用失败了,因为这个 Season 有一个到 Model1 的映射。首先解除它的关联,然后再删除它。 - John Bupit
删除方法可以正常工作,但仍然在父模型中可用,并最终进入process2()。 - ka_lin
它有效:https://dev59.com/_6nka4cB1Zd3GeqPU9yx - Elkin Fajardo
3个回答

6

删除带有条件的hasMany记录:

$model1Instance->seasons()->where('condition', 'met')->delete();

删除全部:

$model1Instance->seasons()->delete();

0

$model->seasons() 返回关联关系,而 $model->seasons 返回映射到模型的 Season 集合。请尝试以下操作。

public function process1($model1Instance) {

    // Iterate over the collection
    for($model1Instance->seasons as $season) {
        if(condition) {
            $model1Instance->seasons()->detach($season); 
            $season->delete();
        }
    }

    $model1Instance->save();
}

此外,您正在迭代所有模型的所有季节,并删除满足某些条件的季节。如果您一次性销毁所有季节,那么效率不会更高吗?可以尝试以下代码:
$seasons = Season::where(condition)->get();
Season::destroy($seasons);

看起来很合理,但出现了问题:未定义方法Illuminate\Database\Query\Builder::sync()。 - ka_lin
你确定你调用的是 $model1Instance->seasons()->sync($childs) 而不是 $model1Instance->seasons->sync($childs) 吗? - John Bupit
在文档中看到:您还可以使用同步方法来构建多对多关联。 - ka_lin
你说得对。sync 只适用于多对多关系。此外,根据文档,你需要在完成后保存模型。请查看更新的答案。 - John Bupit
我正在删除旧的季节,然后添加新的季节,所以不幸的是我不能使用 destroy。 - ka_lin
显示剩余5条评论

0

试试这个

public function process1($model1Instance) {

    // Iterate over the collection
    for($model1Instance->seasons as $season) {
        if(condition) {
            $season->delete();
        }
    }

    $model1Instance->save();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接