Database Laravel工厂-创建或创建动态
我有一个简单的问题 我如何编写一个工厂,让我定义使用Database Laravel工厂-创建或创建动态,database,laravel,testing,factory,relation,Database,Laravel,Testing,Factory,Relation,我有一个简单的问题 我如何编写一个工厂,让我定义使用make()或create()的关系,这取决于原始调用make()或create() 这是我的用例: 我有一个简单的工厂 /**@var$factory\Database\elounce\factory*/ $factory->define(应用程序\用户::类,函数)(Faker$Faker){ 返回[ 'role_id'=>工厂(role::class), 'name'=>$faker->name, 'email'=>$faker->uni
make()
或create()
的关系,这取决于原始调用make()
或create()
这是我的用例:
我有一个简单的工厂
/**@var$factory\Database\elounce\factory*/
$factory->define(应用程序\用户::类,函数)(Faker$Faker){
返回[
'role_id'=>工厂(role::class),
'name'=>$faker->name,
'email'=>$faker->unique()->safeEmail,
“密码”=>“密码”,
];
});
我的问题是角色id的问题。使用工厂(角色::类)
时,它将始终创建一个角色!正在数据库中写入
在我的测试中,当我编写factory(User::class)->create()时代码>它将创建一个用户和角色,没关系
但是如果我写factory(User::class)->make()代码>它仍将创建一个角色。。。使用make()
时,我不会在数据库中编写角色,在这种情况下,我只需要一个简单的Role\u id=>0
我怎样才能做到这一点
谢谢
编辑(变通方法)
嗯,这比预期的要难,当您定义嵌套关系时,无法知道何时使用make()
或create()
。。。我找到的唯一方法是使用debug\u stacktrace()
方法,并查找从工厂调用的make方法
为了简化和重用,我为工厂创建了一个名为associateTo($class)
的助手方法,该方法将定义工厂中的关系。使用create()
时,它将从相关模型返回一个现有ID;使用make()
时,它将返回1
通过这种方式,工厂可以:
/**@var$factory\Database\elounce\factory*/
$factory->define(应用程序\用户::类,函数)(Faker$Faker){
返回[
'role_id'=>associateTo(role::class),//定义关系
'name'=>$faker->name,
'email'=>$faker->unique()->safeEmail,
“密码”=>“密码”,
“记住令牌”=>Str::random(10),
];
});
辅助功能是:
/**
*返回指定模型ID(按类名)的帮助器。
*如果有任何模型,它将随机抓取一个,如果没有,它将使用它的工厂创建一个新模型
*使用make()时,它不会写入数据库,而是返回1
*
*@param string$modelClass
*@param数组$attributes
*@param bool$forceNew
*@return int
*/
函数associateTo(字符串$modelClass,数组$attributes=[])
{
$isMaking=collect(debug\u backtrace())
//一个名为“make()”的函数
->过滤器(fn($item)=>isset($item['function'])和&$item['function']==='make')
//我有全局函数的文件
->过滤器(fn($item)=>isset($item['file'])和&Str::endsWith($item['file'],'functions.php'))
->计数();
如果($isMaking)返回1;
/**@var Model$Model*/
$model=resolve($modelClass);
返回可选($model::inRandomOrder()->first())->id
?创建($modelClass,$attributes)->id;//调用工厂
}
有了它,我可以轻松地编写单元测试(使用工厂),而无需使用数据库连接,因此单元测试变得非常快强>
我希望这能帮助别人 您可以覆盖属性角色id:
factory(User::class)->make(['role_id' => 0]);
另一种解决方案-任何属性的辅助方法,其id为\u
结尾:
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);
你可以利用美国
/**@var$factory\Database\Eloquent\factory*/
$factory->define(应用程序\用户::类,函数(Faker$Faker){
返回[
'role_id'=>工厂(role::class),
'name'=>$faker->name,
'email'=>$faker->unique()->safeEmail,
“密码”=>“密码”,
];
});
$factory->state(应用程序\用户::类,'withoutRelationship'[
'role_id'=>null,
“另一个_id”=>null,
]);
然后
factory(User::class)->state('withoutRelationship')->make();
谢谢您的回答。我知道,但我希望在调用make()
时自动完成,因为如果每次我只想使用factory(…)->make()
,就必须覆盖每个模型的所有关系属性,那就太过分了。。。也许我可以创建一个名为make(MyClass::class)
的测试全局函数,该函数用0覆盖所有“\u id ending”属性,但我仍然不知道如何实现这一点,特别是在嵌套工厂关系中。我添加了帮助器方法谢谢,这很接近,但我无法使用它,因为我正在避免使用数据库,因此,方法getColumnListing()
不起作用,但是,我可以使用Lightlight\Database\Eloquent\Factory:)中的rawOf(class)
),但在定义嵌套关系时仍然失败:(