【发布时间】:2018-05-22 22:04:57
【问题描述】:
我在 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 BUT 的标签,前提是标签分配了正确的 channel_id。如果没有,我会收到以下错误,我可以捕获并处理:
FatalThrowableError (E_ERROR) Call to a member function delete() on null
不过,由于 Apache 是线程化的,在我读取它之后,可能会有另一个线程更改 channel_id。那么除了我的查询之外唯一的方法就是运行一个事务?
【问题讨论】:
-
您应该在数据库中创建外键,以便自动删除该行。
-
我不是删除频道而是删除标签。实际上,有一个外键可以级联频道,但这无济于事,因为我没有删除频道。在 Laravel 的文档中,大多数时候只有一个 Post:destroy($id) 非常好,除了你想在安全问题方面检查另一个标志(user_id、channel_id 等)。
-
我不明白你在做什么。为什么要检索频道
$channel = $this->getChannel();并检查频道ID 是否与->where('channel_id', $channel->id)匹配?第一条语句不应该使第二条语句过时吗? -
我的意思是:您通过这两个查询访问相同的数据。我认为目前没有额外的安全措施。
-
我只是想知道是否有更优雅的方式来实现与使用 Laravel 对象的删除查询相同的功能。简单的方法是获取频道,检查标签中的 channel_id,然后销毁标签。然而,可能有另一个 Apache 进程更改了其间的 channel_id,因此 select 会成功,但 delete 会破坏不允许删除的行(不再)...
标签: php laravel eloquent one-to-many relation