[2.0] Customize Faker's locale
Hello,
in the previous version v1.38.2 I could change the faker local this way but I'm not able anymore to do it. Since v2.* I have this message "Method 'configuration' not found in LocalizedModelFactory"
Here is my code :
abstract class LocalizedModelFactory extends PersistentProxyObjectFactory
{
/**
* @return Proxy<TModel>&TModel
*/
final public static function createOneLocalized(?string $locale = null, array $attributes = []): Proxy
{
if (null !== $locale) {
$locale = sprintf('%s_%s', strtolower($locale), strtoupper($locale));
self::configuration()->setFaker(Factory::create(
sprintf('%s_%s', strtolower($locale), strtoupper($locale))
));
}
$attributes['fakerLocale'] = $locale;
return self::createOne($attributes);
}
Thanks for your help
Maybe @kbond ? Thanks
Hi @camille-guerber
The method Factory::configuration() was marked as @internal in 1.x and should not be used in userland, and no BC policy should be expected from internal class/methods.
By the way, IMO this implementation seems buggy, since you were changing "globally" the faker instance:
$object1 = SomeFactory::createOne(); // faker is used with default, let's say "en_US"
$object2 = SomeFactory::createOneLocalized('fr'); // faker is used with "fr_FR"
$object3 = SomeOtherFactory::createOne(); // faker will still be used with "fr_FR", but "en_US" would have been expected
I think you should consider refactor to something like this:
akbstract class LocalizedModelFactory extends PersistentProxyObjectFactory
{
protected Faker\Generator|null $faker = null;
public function localized(string $local): static
{
$clone = clone $this;
$clone->faker = Faker\Factory::create(
sprintf('%s_%s', strtolower($locale), strtoupper($locale)) // be careful, this might be buggy as well, for instance `en_EN` does not exist
);
return $clone;
}
protected function getFaker(): Faker\Generator
{
return $this->faker ?? self::faker();
}
}
Hello @nikophil thanks for your answer, I'm not able to call "localized" neither "getFaker" from "createOneLocalized" function, any idea ?
I think what you'd need to do is something like this assuming you're extending the abstract class @nikophil suggested:
/**
* @return Proxy<TModel>&TModel
*/
final public static function createOneLocalized(string $locale, array $attributes = []): Proxy
{
return self::new()->localized($locale)->create($attributes);
}
the advantage of having a method localized() is that it's just another state, that could be composed with the other ones:
SomeLocalizedFactory::new()->localized('fr')->withName()->create();
the problem of this approach is that every faker() calls in SomeLocalizedFactory::default() won't be localized...
I've thought a little bit about it on how we could integrate this in Foundry, but I did not find any interesting way to do it, because on how faker works... :shrug:
Thanks @kbond and @nikophil you helped me a lot, what about this ?
/**
* @return Proxy<TModel>[]&TModel[]
*/
final public static function createManyLocalized(int $number, ?string $locale = null, array $attributes = []): array
{
return self::new()->localized($locale)->???
}
Hi,
sorry for the late reply, but what you could do is:
/**
* @return Proxy<TModel>[]&TModel[]
*/
final public static function createManyLocalized(int $number, ?string $locale = null, array $attributes = []): array
{
return self::new()->localized($locale)->many($number)->create();
}
I'm wondering if I won't add this localized() method into Foundry :thinking: