【问题标题】:Laravel Model Observers & RelationsLaravel 模型观察者和关系
【发布时间】:2017-06-30 18:24:48
【问题描述】:

我有一个成员、个人和地址模型。它们与一对一的关系相连。 Member 有一个 Person,Person 有一个 Address,Address 属于 Person,Person 属于 Member 等等。

现在,我的地址也可以属于某个位置...导致 2 个可为空的列,person_idlocation_id

我在Address model 上创建了一个观察者。当我删除成员时,如果设置了location_id,我希望保留地址。

public function deleting(Address $address)
{
    if($address->location_id != null) {
        $address->person_id = null;
        $address->save();
        return false;
    } else {
        return true;
    }
}

奇怪的是,当我使用 ... ->address()->delete(); ... 它会删除该人的地址,并且 Observer 函数不会触发。我必须先单独删除地址$address->delete();,现在 Observer 函数会触发。 我正在考虑的另一个问题,如果反过来呢?删除带有'person_id' 集的位置?

有没有更好的方法来处理删除(可以)属于 2 个不同模型的模型? (仅 OneToOne 关系)。

我在想也许我必须为成员和位置创建 2 个观察者,然后将一个放在地址模型上?或者根本不使用观察者

编辑:

因此可能会出现一个人和一个位置可以具有相同地址的情况。在这种情况下,“person_id”和“location_id”在地址模型上都是 != null。

到目前为止,MemberController 上的所有功能都在工作。就我而言 public function destroy($id) 只会软删除一个成员,并保持 Person 和 Address 不变。

我现在需要解决的只是强制删除,我已经能够想出一些东西,但我不确定什么是好方法。有什么味道:P 当我删除这样的会员时

$member->person()->delete();
$member->forceDelete();

这会奏效。但我必须做 3 次删除? (包括地址)。 同样删除地址应该取决于 location_id 的存在,因为当地址也属于某个 Location 时,我希望保留该地址,而是将 person_id 设置为 null。

我已经通过在地址模型上创建一个观察者来尝试这个,但是我面临着不知道成员或位置是否被删除的问题,所以我不确定应该检查哪个“_id”是否为空。

我面临的另一个问题是,当我删除 Member->relation()-> 方式时,观察者函数不会触发。它似乎只在我单独删除地址时才起作用 $address->delete(); 因此,我怀疑观察者是否是一个好方法,也许我应该在成员/位置控制器中这样做。

/**
 * Permanently remove the specified resource from storage.
 *
 * @param int $id
 * @return Response
 */
public function remove( $id )
{
    $member = $this->model->onlyTrashed()->find( $id );

    $address = $member->person->address;
    if($address->location_id != null) {
        $address->person_id == null;
        $address->save();
    } else {
        $address->delete();
    }

    $member->person()->delete();
    $member->forceDelete();

这会奏效,甚至可以让它变得愚蠢简单?但我不确定在这里做这个地址的东西是否是一个好方法,只是想学习。

会员 | hasOne - 属于 |人 | hasOne - 属于 |地址 |属于-hasOne |位置

【问题讨论】:

  • 你有点失去我了。您能否准确总结一下您所追求的以及您想要/不想发生的事情?
  • 我已经编辑了我的问题 ;) sry
  • 你有一个多态关系顺便说一句:laravel.com/docs/5.8/…

标签: laravel one-to-one observers


【解决方案1】:

运行$member->relation()->delete(); 之类的东西时,您无法让观察者触发的原因是$member->relation() 只会返回Builder 的实例。当您在Builder 上调用delete() 时,它只会执行查询,实际上不会新建模型,这反过来意味着永远不会触发事件。要触发事件,您只需执行 $member->relation->delete();

如果我理解您的问题是正确的,那么您可以向 Person 模型添加一个侦听器/观察者,该模型将删除没有位置的地址或创建 person_id null 如果它确实:

protected static function boot()
{
    parent::boot();

    static::deleting(function (self $person) {

        if (is_null($person->address->location_id)) {
            $person->address->delete();
        } else {
            $person->address->person_id = null;
            $person->address->save();
        }

    });
}

然后在您的 Member 模型中,您可以添加另一个删除侦听器,该侦听器还检查模型是否被强制删除:

protected static function boot()
{
    parent::boot();

    static::deleting(function (self $member) {

        if ($member->forceDeleting) {
            $member->person->delete();
        }
    });
}

使用上面的$member->delete() 不会删除人员或地址,但是,$member->forceDelete() 会导致人员和地址都被删除(但地址仅在不属于位置)。

希望这会有所帮助!

【讨论】:

  • 嗯,我喜欢你将它保存在模型中的方式,所以其他人不必到处查看。它会使我的删除功能在成员内部保持简短......我认为我将作为对 MemberController 的评论,说它也会删除相关模型,除非......我想在 Person 模型中进行 null 检查,然后在 Member 控制器中进行检查更有意义......我想我以前见过这样的事情,那么做 parent::boot 怎么样?
  • 是的,您对parent::boot(); 的看法完全正确!哈哈,对不起,我完全错过了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
相关资源
最近更新 更多