実現したいこと
Laravel8にて、テストデータを作成しています。テストデータはユーザーID単位でユニークなIDを得るように操作したいと思っています。
前提
LaravelのFactory機能を利用して作成しています。
以下の構文で実現するものと思って記述しました。
// ユーザー毎に店を決める public function specify_user($user_id) { return $this->state(function (array $attributes) use ($user_id) { $temp_val = $user * 100; return [ 'user_id' => $user_id, 'shop_id' => $this->faker ->unique() ->numberBetween(1 + $temp_val, 20 + $temp_val) - $temp_val, ]; }); }
なお、呼び出し側は以下のように、作成数は乱数となっています。
public function run() { for($i = 1; $i < 11 ; $i++){ $choice = Choice::factory() ->count(random_int(0, 5)) ->specify_user($i) ->create(); } }
このコードでは時たまうまくいきますが、100%ではありません。乱数の発生次第ではエラーが発生します。
発生している問題・エラーメッセージ
発生するエラーは乱数計算の上限に達したとのメッセージが発生します。
In UniqueGenerator.php line 80: Maximum retries of 10000 reached without finding a unique value
試したこと
被らないようにチェックするようにしたコードに置き換えてみましたが、やはり、うまくいきません。
public function specify_user($user_id) { return $this->state(function (array $attributes) use ($user_id) { $temp_val = $user_id * 100; $used_numbers = \DB::table('favorites') ->where('user_id', $user_id) ->pluck('restrant_id') ->toArray(); $restaurant_id = $this->uniqueRandomNumber(1 + $temp_val, 20 + $temp_val, $temp_val, $used_numbers); return [ 'user_id' => $user_id, 'restrant_id' => $restaurant_id, ]; }); } public function uniqueRandomNumber($min = 1, $max = 20, $temp_val = 0, $exclude = []) { $number = $this->faker->numberBetween($min, $max) - $temp_val; $attempts = 0; while (in_array($number, $exclude) && $attempts < 10000) { $number = $this->faker->numberBetween($min, $max); $attempts++; } if ($attempts == ($max - $min)) { throw new \Exception("All numbers between $min and $max have been used."); } return $number; }
こちらのコードの場合は、ユーザーID単位でユニークなIDが大概算出できず、
SQLSTATE[23000]: Integrity constraint violation
でエラーになります。
補足情報(FW/ツールのバージョンなど)
Laravel : 8.83.26
0 コメント