Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database Laravel工厂-创建或创建动态_Database_Laravel_Testing_Factory_Relation - Fatal编程技术网

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)
),但在定义嵌套关系时仍然失败:(