現象
ある日上手くテストが動かなかった。。。
$ php artisan tinker
> fake()->regexify("/[ぁ-ん]{6}/")
= b"ôôü-Ò-"
> fake()->regexify("/[ぁ-ん]{6}/u")
= b"ÒéÒüÒÒ/u"
謎の文字化け タスケテ...
調査
Faker は今 FakerPHP
に置き変わってる
regexify()
の実コードはここ
なんか色んなことやってる
ランダムを実現するために、正規表現を読み取って文字を当てはめてるみたい
すごい地道なコードだ...
正規表現の区切り文字 '/.../' と開始/終了マーカー '^...$' は無視されます。
正規表現構文の小さなサブセットのみをサポートします。たとえば、
Unicode、否定クラス、無制限の範囲、サブパターン、後方参照、
アサーション、再帰パターン、コメントはサポートされていません。エスケープ
サポートは非常に脆弱です。このメソッドは非常に低速です。他のフォーマッタが
必要な偽のデータを生成できない場合にのみ使用してください。たとえば、以前の正規表現でregexify
を呼び出すのではなく、$faker->email
を呼び出すことを推奨します。また、
bothify
はおそらくこのメソッドが行うことのほとんどを実行できますが、はるかに高速です。たとえば、ダミーの電子メールを生成するには、$faker->bothify('?????????@???.???')
を試してください。
だそう!!!
そりゃ日本語に対応してないわ
bothify()
ってのも初めて知った
regexify()
はあんまり使わないほうが良さそうだね
対策
色々あるが mb_chr
を使ってみる
Unicodeでひらがなの範囲は \u3040-\u309F
これを10進数に変更すると 12352-12447
つまりランダムな数値を生成すれば、ひらがなが生成できる
> mb_chr(fake()->numberBetween(12352, 12447))
= "た"
> mb_chr(fake()->numberBetween(12352, 12447))
= "む"
> mb_chr(fake()->numberBetween(12352, 12447))
= "ね"
成功
これを Faker
に登録する
参考記事:
<?php
namespace App\Faker\Provider;
use Faker\Provider\Base;
class Hiragana extends Base
{
/**
* ひらがなの生成
*
* @param integer $length 長さ
* @return string
*/
public function hiragana(int $length = 1): string
{
return collect(range(1, $length))
->reduce(fn ($stack) => $stack .= mb_chr(fake()->numberBetween(12352, 12447)), '');
}
}
// ...
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// ...
// Faker 拡張
$faker = fake();
$faker->addProvider(new Hiragana($faker));
}
// ...
}
これで成功!
> fake()->hiragana();
= "お"
> fake()->hiragana(10);
= "えだらそかいみぁるき"
こんな簡単にできるなら、拡張ライブラリ作ってもいいかも!