如何从 Laravel 5.5 中的一对多关系中删除单行(多行)

How to delete single (many-) rows from one-to-many relations in Laravel 5.5

我在 Laravel 中得到了两个模型:标签

class Label extends \Eloquent
{
    protected $fillable = [
        'channel_id',
        'name',
        'color',
    ];

    public function channel()
    {
        return $this->belongsTo('App\Channel');
    }
}

和频道

class Channel extends \Eloquent
{
    protected $fillable = [
        'name',
    ];

    public function labels()
    {
        return $this->hasMany('App\Label');
    }

}

现在当一个标签被删除时,我想确定这个标签是否属于该频道。

这非常有效,因为它甚至是原子的,所以如果标签确实属于该频道,则该行将被删除。

标签控制器:

/**
 * Remove the specified resource from storage.
 *
 * @param  int $id
 * @return \Illuminate\Http\Response
 */
public function destroy($id)
{
    $channel = $this->getChannel();

    Label::where('id', $id)
        ->where('channel_id', $channel->id)
        ->delete();

    return back();
}

现在我的问题是:如何使用 Eloquent 构建它,使其优雅?类似于:

    $channel->labels()->destroy($id);

但是关系上没有销毁函数。

更新:

我在正确的方向上取得了一些成就:

$channel->labels()->find($id)->delete();

这将删除带有 $id 的标签,但前提是该标签具有正确的 channel_id 分配。如果没有,我会收到以下错误,我可以捕获并处理:

FatalThrowableError (E_ERROR) Call to a member function delete() on null

不过,由于 Apache 是线程化的,因此在我阅读 channel_id 后,可能会出现另一个线程更改它的情况。所以除了我的查询之外,唯一的方法是 运行 交易?

如果您想删除模型的相关项目而不是模型本身,您可以这样做:

$channel->labels()->delete(); 将删除与频道相关的所有标签。

如果您只想删除部分标签,可以使用 where()

$channel->labels()->where('id',1)->delete();

此外,如果您的关系是多对多关系,它也会从第三个 table 中删除。

您提到过,您首先要检查标签是否有频道。如果是这样,那么应该删除它。

虽然你可以尝试这样的事情:

$label = Label::find($id);
if ($label->has('channel')) {
    $label->delete();
}

您可以使用 findorfail:

$channel->labels()->findOrFail($id)->delete();