删除父更新上的集合之一


Deleting one of a collection on parent update

我正在尝试在更新时删除(或创建)模型关联的对象。每个酒吧都有几个水龙头。创建条形图时,将创建这些点击对象,您可以更新该数字,并根据需要创建或删除其他点击。

最初我只是想像这样使用pop

        $taps=$bar->taps;
        if ( $taps_old < $taps_new){
            for ($i = $taps_old; $i < $taps_new; $i++) {
                $tap = Growlertap::create(['growlerstation_id' => $id]);
            }
        }
        elseif ($taps_old > $taps_new) {
            for ($i = $taps_new; $i < $taps_old; $i++) {
                $taps->pop();
            }

这不起作用,但不会给我错误。我知道 if 语句工作正常,因为下面的代码有效:

        elseif ($taps_old > $taps_new) {
            for ($i = $taps_new; $i < $taps_old; $i++) {
                Beertap::where('bar_id', '=', $id)->first()->delete();
            }
        }

这似乎不是最简单的写法。有没有更好的写法?

顺便说一下,对于那些想知道的人,这是我在控制器中的更新功能中。

>pop()将删除本地集合中的最后一项,但它不会将该更改保留到数据库中。

假设它是一个Beertap对象,这样的东西应该可以工作:

警告:未经测试的代码

    ...
    elseif ($taps_old > $taps_new) {
        for ($i = $taps_new; $i < $taps_old; $i++) {
            $delete_me = $taps->pop();
            $delete_me->delete();
        }
    }

或更简洁地说:$taps->pop()->delete();

这应该有效 不幸的是,这不起作用,因为 DELETE 语句不支持偏移量。

Beertap::where('bar_id')->skip($taps_new)->delete();

因此,它会跳过您想要保留的任意数量的点击并删除其余的点击。如果删除哪些行很重要,则可能需要使用 orderBy

更新

这现在应该完全有效。首先获取要从集合中删除的所有 id,然后通过一个查询将其删除

$idsToDelete = $taps->slice($taps_new)->modelKeys();
Beertap::destroy($idsToDelete);

更新 2

您也可以优化创建过程(以便在单个查询中完成)

$data = [];
for ($i = $taps_old; $i < $taps_new; $i++) {
    $data[] = ['growlerstation_id' => $id];
}
Beertap::insert($data);

请注意,在选择使用 insert() 时,您将失去自动时间戳和模型事件等 Eloquent 功能。