我有一个简单的问题。
如何编写一个Factory,让我根据原始调用make()
或create()
定义使用make()
或create()
的关系?
这是我的用例:
我有一个简单的工厂
/** @var $factory Illuminate\Database\Eloquent\Factory */
$factory->define(App\User::class, function (Faker $faker) {
return [
'role_id' => factory(Role::class),
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => 'secret',
];
});
我的问题是那个 role_id 。使用factory(Role::class)
时,它将始终创建一个角色!用数据库编写...
在测试中,当我编写factory(User::class)->create();
时,它将创建一个用户和角色,没关系!
但是如果我写factory(User::class)->make();
仍会创建一个角色...使用make()
时我不会在数据库中写一个角色,在那种情况下,我只想要一个简单的role_id => 0
我该如何实现?
谢谢!
编辑(解决方法)
好吧,这比预期的要难,当您定义嵌套关系时,没有办法知道何时使用make()
或create()
...我发现的唯一方法是使用{{1} }方法,然后查找从Factory调用的make方法。
为了简化和重用性,我为工厂创建了一个名为debug_stacktrace()
的工厂助手方法,该方法将定义Factory中的关系。使用associateTo($class)
时将返回相关模型的现有ID,使用create()
时将返回1。
通过这种方式,工厂可以成为:
make()
助手功能是:
/** @var $factory Illuminate\Database\Eloquent\Factory */
$factory->define(App\User::class, function (Faker $faker) {
return [
'role_id' => associateTo(Role::class), // Defining relationship
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => 'secret',
'remember_token' => Str::random(10),
];
});
有了这个,我可以轻松地(使用工厂)编写单元测试,而无需使用数据库连接,因此单元测试变得非常快!
希望这对其他人有帮助!
答案 0 :(得分:0)
您可以覆盖属性 role_id :
factory(User::class)->make(['role_id' => 0]);
另一种解决方案-以_id
结尾的任何属性的辅助方法:
function make($class)
{
$attributes = \Schema::getColumnListing((new $class)->getTable());
$exclude_attribures = [];
foreach ($attributes as $attribute)
{
if(ends_with($attribute, '_id'))
{
$exclude_attribures[] = [$attribute => 0];
}
}
return factory($class)->make($exclude_attribures);
}
通话示例:
make(User:class);
答案 1 :(得分:0)
您可以利用状态
/** @var $factory Illuminate\Database\Eloquent\Factory */
$factory->define(App\User::class, function (Faker $faker) {
return [
'role_id' => factory(Role::class),
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => 'secret',
];
});
$factory->state(App\User::class, 'withoutRelationship', [
'role_id' => null,
'another_id' => null,
]);
然后
factory(User::class)->state('withoutRelationship')->make();