Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.0] Customize Faker's locale #662

Open
camille-guerber opened this issue Jul 1, 2024 · 7 comments
Open

[2.0] Customize Faker's locale #662

camille-guerber opened this issue Jul 1, 2024 · 7 comments

Comments

@camille-guerber
Copy link

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

@camille-guerber camille-guerber changed the title customize Faker's locale [2.0] Customize Faker's locale Jul 1, 2024
@camille-guerber
Copy link
Author

Maybe @kbond ? Thanks

@nikophil
Copy link
Member

nikophil commented Jul 3, 2024

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();
	}
}

@camille-guerber
Copy link
Author

Hello @nikophil thanks for your answer, I'm not able to call "localized" neither "getFaker" from "createOneLocalized" function, any idea ?

@kbond
Copy link
Member

kbond commented Jul 4, 2024

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);
    }

@nikophil
Copy link
Member

nikophil commented Jul 4, 2024

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... 🤷

@camille-guerber
Copy link
Author

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)->???
}

@nikophil
Copy link
Member

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 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants