首页 > 解决方案 > 如何将现有模型作为多对多关系添加到 laravel 中的 dummy_mode

问题描述

我正在尝试在 laravel 中制作一个测试用例。

  1. 我有一个假的 用户模型(它存在于数据库中),并使用创建它faker->make

  2. 以及存在于数据库中的真实 角色模型,

这两个有一个多对多的关系

在我的测试用例中,我将像这里一样关联它们:

public function testAccess()
{
        $user = factory(\App\User::class)->make();
        $supervisionControllerRole = \App\Role::where('name', 'supervision_controller')->first();
        $user->roles->add($supervisionControllerRole);
}

因为我不想将关系保存在数据库中,所以我使用add()而不是attach()

$user->roles()->attach($supervisionControllerRole->id);
//resulting database modification.

问题

我的问题是,当我试图从模型中获取关系时,它可以。

var_dump($user->roles->first());

但是当我试图获得模型内的关系时,它会起作用。

就像在我的User模型中一样:

public function hasRole($roleName)
{
    $role_id = Cache::tags(['role_id'])->remember($roleName, 24*3600, function () use ($roleName) {
        return \App\Role::where('name', $roleName)->first()->id;
    });
    return $this->roles()->where('role_id', $role_id)->exists();
}

它将 从模型内部returns false尝试$this->roles->count()结果。0

我的定义

User模型中:

public function roles()
{
    return $this->belongsToMany("App\Role", "role_user")->whereNull("deleted_at")->using("App\RoleUser");
}

用户工厂:

$factory->define(User::class, function (Faker $faker) {
    return [
        'id' => $faker->randomNumber(),
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => Str::random(80), // password
        'remember_token' => Str::random(10),
    ];
});

标签: phplaravelunit-testingeloquenteloquent-relationship

解决方案


每当您调用带括号的关系时,例如

return $this->roles()->where('role_id', $role_id)->exists();
                   ^^

您正在访问一个Builder查询实例,该实例将从数据库返回信息。但是您的数据不在数据库中,所以当它在那里查找时当然不会找到任何东西。

当您直接add()建立关系 (vs attach()) 时,您将插入一个Collection实例,您知道这不会影响数据库。此信息仅保存在模型上并存储在内存中。因此,当你这样做

var_dump($user->roles->first());

它找到信息,因为它已经在内存中。(您也应该能够在$user->roles->count()这里调用并获得一个非零值。)

而且由于它是模型与直接属性的关系,我什至认为如果您save()使用模型它不会更新数据库。

如果您不存储在数据库中,您可以使用该contains方法执行第一步:

return $this->roles->contains($role_id);

推荐阅读