skip to Main Content

My question is quite similar to this unanswered question.

I’m making a 2v2 ladder system in Laravel 11. I have 2 models:

  • Users
  • Games

There’s a pivot table between them with an added team_user column, defining which team the user is on.

Users can have unlimited games, but a game has only 4 players, and their team in that game defined by aforementioned pivot column.

My seeder function looks like this currently:

$users = User::factory(20)->create();

Game::factory(100)
  ->hasAttached($users->random(2), [
    'user_team' => 'team1'
  ])
  ->hasAttached($users->random(2), [
    'user_team' => 'team2'
  ])
  ->create();

This kinda works. 20 users and 100 games are created, but the same 4 users are used for every game.
If I plug in the User::factory() directly into hasAttached(), it will generate new users for every single game.

What I want is 20 users randomly playing on teams in all 100 games (but also not end up with the same user multiple times in the same game).

I hope what I’m trying to do makes sense!

2

Answers


  1. Why does end up with the same 4 users used for every game?
    because Laravel factory runs the two calls of the hasAttach method just once and applies them on entire the collection not run them on each game

    You can try this

    $users = User::factory(20)->create();
    
    Game::factory(100)->create()->each(function ($game) use ($users) {
        // Shuffle users for random selection
        $shuffledUsers = $users->shuffle();
    
        // Assign two users to team1 and two users to team2
        [$team1Users, $team2Users] = $shuffledUsers->chunk(2);
    
        // Attach users to the game with their respective teams
        $game->users()->attach($team1Users, ['user_team' => 'team1']);
        $game->users()->attach($team2Users, ['user_team' => 'team2']);
    });
    
    Login or Signup to reply.
  2. I think you can run GameFactory in a loop with minimum code changes

    This time on each cycle users will be picked randomly every time

    $users = User::factory()->count(20)->create();
    
    for ($i=0; $i < 100; $i++) {
        Game::factory() // one model per iteration
            ->hasAttached($teamOne = $users->random(2), ['user_team' => 'team_1'])
            ->hasAttached($users
                ->whereNotIn('id', $teamOne->pluck('id')) // prevent users from team one to play against themselves
                ->random(2), ['user_team' => 'team_2'])
            ->create();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search