laravel 观察者将一个表添加到透视表中,并立即删除相同的行

aamkag61  于 2023-11-20  发布在  其他
关注(0)|答案(1)|浏览(157)

我有两个模型User和Role多对多关系通过透视表。User:

public static function boot(): void
{
     parent::boot();
     self::observe(new UserObserver());
}

public function roles(): belongsToMany
{
     return $this->belongsToMany(
            Role::class,
            'role_user_table',
            'user_id',
            'role_id'
      )->using(RoleUser::class);
}

字符串
角色用户模型

class RoleUser extends Pivot
{
    use CrudTrait;
    use HasFactory;

    protected $table = 'role_user_table';

    public $incrementing = true;

    protected $fillable = [
        'id',
        'user_id',
        'role_id',
    ];
}


UserObserver

public function saved(User $model): void
    {
        $this->model = $model;
        if ($this->model->all_roles) {
            $roles= Role::pluck('id')->toArray();
            $this->model->roles()->syncWithoutDetaching($roles);
        }
    }


我在日志中(以及staging表中的自动增量)看到observer向pivot表添加行,然后删除它们。我不明白为什么会发生这种情况。在这种情况下,如果您将syncWithoutDetaching的结果保存到变量中并通过dd()输出。数组将正确返回。
解决方法:
正如我已经在评论中所写的那样,可能值得指出的是,我使用了一个粗糙的背包。在澄清观察者的奇怪行为的过程中,我注意到,在日志中,观察者工作正常,无论我使用什么同步方法(同步、附加、分离等),我做的第一件事就是使用backpack的功能,并将保存的方法放置在setuptask操作方法中,如图所示它的工作方式与简单的观察者完全相同--它添加然后删除行。

public function setupCreateOperation()
{
    User::saved(function($entry) {
        $roles= Role::pluck('id')->toArray();
        $entry->roles()->syncWithoutDetaching($roles);
    });
}


然后我开始理解store和update方法。通过将我的同步代码放在默认的create和update trait之后,我的代码工作,因为它应该.显然,这些特质以某种方式保持列的状态,并试图改变他们执行前遇到回滚值.相当奇怪的行为.这是第二次我'我见过他,但上次我们在不了解其原理的情况下绕过了他们。

public function store()
{
    $response = $this->traitStore();
    // do something after save
    $this->syncRoles($this->data['entry']->id, $this->data['entry']->all_roles);
    return $response;
}

public function udate(UserRequest $request)
{
    $response = $this->traitUpdate();
    // do something after update
    $this->syncRoles($request['id'], $request['all_roles']);
    return $response;
}

public function syncRoles(int $id, int $all_roles): void
{
    if ($all_roles) {
        $roles = Role::pluck('id')->toArray();
        User::find($id)->role()->syncWithoutDetaching($roles);
    }
}

6yoyoihd

6yoyoihd1#

看起来你遇到了一个问题,你的UserObserver正在向数据透视表添加行,然后又删除了它们。这可能是由于Eloquent的syncWithoutDetaching方法的工作方式。
syncWithoutDetaching方法通常用于同步相关记录而不分离任何现有记录。在UserObserver中,您正在使用它来同步用户的角色。但是,同步似乎没有按预期工作。
这里有一些你可以检查和考虑的事情:
1.检查“all_roles”属性:确保用户模型的“all_roles”属性已正确设置以触发同步操作。如果未正确设置,可能会导致意外行为。
1.检查触发条件:确保观察者在正确的时间被触发。如果触发太频繁,可能会导致不必要的同步操作。检查观察者如何以及何时附加到User模型。
1.数据库约束:检查透视表(“role_user_table”)上是否存在可能干扰同步操作的任何数据库约束或触发器。唯一键或外键等约束可能会影响行为。
1.日志记录和备份:您提到syncWithoutDetaching返回的数组是正确的。在这种情况下,您可能需要添加更多的日志记录和调试语句来跟踪观察器和同步操作的流程。这可以帮助您确定删除行的确切点。
1.替代方法:如果问题仍然存在,并且您无法确定根本原因,您可以考虑同步角色的替代方法。例如,您可以通过将现有角色与新角色进行比较并相应地更新数据透视表来手动管理同步操作。
在没有看到完整代码和数据库结构的情况下,很难确定确切的问题。但是,通过遵循这些步骤并仔细检查同步过程,您应该能够识别并解决问题。

相关问题