Laravel 模型观察者和关系

Laravel Model Observers & Relations

我有一个 Member、Person 和 Address 模型。它们与一对一关系相关联。 Member 有一个 Person,Person 有一个 Address,Address 属于 Person,Person 属于 Member 等等

现在,我的地址也可以属于一个位置...产生 2 个可为空的列,person_id & location_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 关系)。

我在想也许我必须为 Member 和 Location 创建 2 个 Observer,然后将其中一个放到 Address 模型中?或者根本不使用观察者

编辑:

所以可能会出现一个人和一个地点可以有相同地址的情况。在这种情况下,'person_id' 和 'location_id' 在 Address 模型上都是 != null。

到目前为止,我已经可以使用 MemberController 上的所有功能。就我而言 public 函数 destroy( $id ) 只会软删除一个成员,并保持 Person 和 Address 不变。

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

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

这行得通。但我必须做 3 次删除? (包括地址)。 另外删除一个地址应该取决于location_id的存在,因为当一个地址也属于一个Location时,我希望保留该地址,而是将person_id设置为null。

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

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

/**
 * 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();

这行得通,甚至可能是保持愚蠢简单的情况?但我不确定在这里做这个 Address 的东西是否是一个好方法,只是想学习。

会员 | hasOne - 属于 |人 | hasOne - 属于 |地址 |属于 - hasOne |地点

当 运行 类似 $member->relation()->delete(); 的时候你无法让你的观察者开火的原因是因为 $member->relation() 只是 return [=] 的一个实例14=]。当您在 Builder 上调用 delete() 时,它只会执行查询,而不会实际新建模型,这反过来意味着永远不会触发事件。要触发事件,您只需执行 $member->relation->delete();

如果我理解你的问题是正确的,那么你可以将 listener/observer 添加到 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() 会导致人和地址都被删除(但地址只有在不删除时才会被删除'也属于某个位置)。

希望对您有所帮助!