Dependency injection 模型工厂内部的依赖项注入

Dependency injection 模型工厂内部的依赖项注入,dependency-injection,laravel-5,Dependency Injection,Laravel 5,这是我的第一个问题,所以我也希望得到关于如何正确提问的提示 因此,在我的Laravel应用程序中,我有一个包含用户的数据库表。首先,我想为它建立一个模型工厂。因此,我采用了以下标准代码: 我把它改成: $factory->define(App\User::class, function(Faker\Generator $faker) { return [ 'name' => $faker->name(),

这是我的第一个问题,所以我也希望得到关于如何正确提问的提示

因此,在我的Laravel应用程序中,我有一个包含用户的数据库表。首先,我想为它建立一个模型工厂。因此,我采用了以下标准代码:

我把它改成:

$factory->define(App\User::class,
                    function(Faker\Generator $faker) {

    return [
        'name' => $faker->name(),
        'email' => $faker->safeEmail(),
        'password' => bcrypt(str_random(10)),
        'phone_number' => $faker->phoneNumber(),
        'remember_token' => str_random(10),
        'account_type' => 0,
    ];

});
$factory->define(App\User::class,
                    function(Faker\Generator $faker,
                             Faker\Provider\it_IT\PhoneNumber $fakerITPN,
                             Faker\Provider\it_IT\Person $fakerITPER,
                             Faker\Provider\it_IT\Internet $fakerITInt) {

    return [
        'name' => $fakerITPER->name(),
        'email' => $fakerITInt->safeEmail(),
        'password' => bcrypt(str_random(10)),
        'phone_number' => $fakerITPN->phoneNumber(),
        'remember_token' => str_random(10),
        'account_type' => 0,
    ];

});
到目前为止,一切正常。但我希望它更复杂,我决定使用更具体的伪造类来生成意大利数据。我把它改成:

$factory->define(App\User::class,
                    function(Faker\Generator $faker) {

    return [
        'name' => $faker->name(),
        'email' => $faker->safeEmail(),
        'password' => bcrypt(str_random(10)),
        'phone_number' => $faker->phoneNumber(),
        'remember_token' => str_random(10),
        'account_type' => 0,
    ];

});
$factory->define(App\User::class,
                    function(Faker\Generator $faker,
                             Faker\Provider\it_IT\PhoneNumber $fakerITPN,
                             Faker\Provider\it_IT\Person $fakerITPER,
                             Faker\Provider\it_IT\Internet $fakerITInt) {

    return [
        'name' => $fakerITPER->name(),
        'email' => $fakerITInt->safeEmail(),
        'password' => bcrypt(str_random(10)),
        'phone_number' => $fakerITPN->phoneNumber(),
        'remember_token' => str_random(10),
        'account_type' => 0,
    ];

});
在播种机课程中,我写道:

factory(App\User::class)->create();
然后,在我使用Artisan之后,命令:

artisan migrate:refresh --seed -vvv
我得到以下错误(仅头部,用于清除):


显然,依赖注入有问题,但我不知道是什么。我知道,在这种情况下,我可以手动创建我需要的类的实例,但我想知道,如何正确地执行。有人能帮忙吗?

如果你看一看faker@的文档,你会发现你可以简单地指定适当的本地化作为参数来创建

在您的情况下,只需使用:

Faker\Factory::create('it_IT');
定义工厂时,无需在匿名函数中添加更多参数

编辑:

只是补充一下依赖注入的问题。如果跟踪源代码,它不会在下面执行任何依赖项注入

$factory->define(...)
仅设置定义数组

public function define($class, callable $attributes, $name = 'default')
{
    $this->definitions[$class][$name] = $attributes;
}
召唤

Faker\Factory::create();

调用实例化FactoryBuilder的“of”方法 (参见illumb\Database\Eloquent\Factory.php的第169-172行)

在此之后,它链接FactoryBuilder的“create”方法,该方法调用“make”方法,该方法也调用“makeInstance”

请注意“makeInstance”中的“call_user_func”,它负责调用作为要定义的第二个参数创建的匿名函数(在ModelFactory.php内部)。它只向可调用函数传递2个参数,它们是:

...$this->faker, $attributes);
在第一个参数上只传递1个faker,在第二个参数上传递一个属性数组(这是您之前在ErrorException上看到的)

这意味着您只能通过以下方式定义工厂:

$factory->define(App\User::class, 
    function (Faker\Generator $faker, $attributes=array()) {

    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});
如果确实需要其他类,可以在“define”之外对其进行初始化,并在函数中使用,如下所示:

$sampleInstance = app(App\Sample::class);

$factory->define(App\User::class, 
    function (Faker\Generator $faker, $attributes=array()) use($sampleInstance){

    //...do something here 
    //...or process the $attributes received
    //...or call a method like
    $sampleData = $sampleInstance->doSomething();        

    return [
        'someField' => $sampleData,
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});

如果你看一下faker@的文档,你会发现你可以简单地指定适当的本地化作为参数来创建

在您的情况下,只需使用:

Faker\Factory::create('it_IT');
定义工厂时,无需在匿名函数中添加更多参数

编辑:

只是补充一下依赖注入的问题。如果跟踪源代码,它不会在下面执行任何依赖项注入

$factory->define(...)
仅设置定义数组

public function define($class, callable $attributes, $name = 'default')
{
    $this->definitions[$class][$name] = $attributes;
}
召唤

Faker\Factory::create();

调用实例化FactoryBuilder的“of”方法 (参见illumb\Database\Eloquent\Factory.php的第169-172行)

在此之后,它链接FactoryBuilder的“create”方法,该方法调用“make”方法,该方法也调用“makeInstance”

请注意“makeInstance”中的“call_user_func”,它负责调用作为要定义的第二个参数创建的匿名函数(在ModelFactory.php内部)。它只向可调用函数传递2个参数,它们是:

...$this->faker, $attributes);
在第一个参数上只传递1个faker,在第二个参数上传递一个属性数组(这是您之前在ErrorException上看到的)

这意味着您只能通过以下方式定义工厂:

$factory->define(App\User::class, 
    function (Faker\Generator $faker, $attributes=array()) {

    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});
如果确实需要其他类,可以在“define”之外对其进行初始化,并在函数中使用,如下所示:

$sampleInstance = app(App\Sample::class);

$factory->define(App\User::class, 
    function (Faker\Generator $faker, $attributes=array()) use($sampleInstance){

    //...do something here 
    //...or process the $attributes received
    //...or call a method like
    $sampleData = $sampleInstance->doSomething();        

    return [
        'someField' => $sampleData,
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});

您可以将此设置放入AppServiceProvider的register()中:

$this->app->singleton(\Faker\Generator::class, function () {
        return \Faker\Factory::create('it_IT');
});

您可以将此设置放入AppServiceProvider的register()中:

$this->app->singleton(\Faker\Generator::class, function () {
        return \Faker\Factory::create('it_IT');
});

谢谢,说得好!但问题是,如果我想在这个匿名函数中定义其他参数,我应该怎么做?特别是,如何像这样初始化类的对象?或者说写得好的代码是不可能的,或者说是没有必要的?@Staszek我已经更新了我的答案来解决你的问题concern@Staszek如果它很好地解决了你的问题,请接受它作为回答。很久以前就已经这样做了。由于缺少声望点数,无法升级。再次感谢!别担心。谢谢@staszekThanke,说得好!但问题是,如果我想在这个匿名函数中定义其他参数,我应该怎么做?特别是,如何像这样初始化类的对象?或者说写得好的代码是不可能的,或者说是没有必要的?@Staszek我已经更新了我的答案来解决你的问题concern@Staszek如果它很好地解决了你的问题,请接受它作为回答。很久以前就已经这样做了。由于缺少声望点数,无法升级。再次感谢!别担心。谢谢@Staszek