0

I running into what I assume is so simple I am just overthinking it. I am running the following commands in my Tinker session and it is working as expected:

   $game = Games::find(1);
[!] Aliasing 'Games' to 'App\Models\Games' for this Tinker session.
=> App\Models\Games {#4386
     id: 1,
     user_id: 1,
     title: "Test Game",
     description: "This is a test of the game function",
     max_players: 8,
     deck: "default",
     type: "Golf",
     privacy: "Public",
     current_player: null,
     status: "pending",
     deleted_at: null,
     created_at: "2020-12-18 22:02:17",
     updated_at: "2020-12-18 22:02:17",
   }
>>> $game->players()->get();
=> Illuminate\Database\Eloquent\Collection {#4322
     all: [
       App\Models\User {#4384
         id: 1,
         name: "mark",
         email: "test@test.com",
         username: "user",
         role: null,
         email_verified_at: null,
         created_at: "2020-12-18 22:02:08",
         updated_at: "2020-12-18 22:02:08",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4168
           games_id: 1,
           user_id: 1,
         },
       },
     ],
   }

I have essentially placed that exact same code in my controller to pull a list of players in a game:

    $game = Games::find($game);
    $players = $game->players()->get();

and I am getting this when I hit the route:

Method Illuminate\Database\Eloquent\Collection::players does not exist.

I am confused why this wouldnt work in the controller if it works just fine in Tinker.

Thanks for the help!

Ethicist
  • 791
  • 2
  • 7
  • 23
Markwow
  • 141
  • 9
  • 2
    In your controller code, you have `$game = Games::find($game);`. Is the parameter passed into `find()` a typo? If not, would it happen to be an array? – patricus Dec 18 '20 at 22:52
  • And try to use $game = Game::findOrFail($id) so that if no record exists in the database for the given id, you don't get an error "Trying to access players() on null" error – Donkarnash Dec 18 '20 at 22:59
  • 1
    Patricus, it was an array, ugh silly mistakes always take the longest. Thank you for your help! Donkarnash I will switch that out as well! – Markwow Dec 18 '20 at 23:00
  • 1
    And, you can access relations as properties like `$players = $game->players` or eager load the players right into the game with `Game::with('players')->find($id);` – miken32 Dec 18 '20 at 23:15
  • Miken32 that actually cuts out some code for me eager loading them in with the game. Saves me a separate call to get the players since I am already calling the game. Thank you! – Markwow Dec 20 '20 at 00:10

2 Answers2

1
$game = Games::find($game);

If you pass a single id to find, it will return a Game model or null. But if you pass an array of ids (even if it's an array of length 1) or a Model (for some reason), it will return a Collection or null.

In your tinker session, try this and you'll have the same error thrown.

$game = Games::find(1);
$game = Games::find($game);
// or
$game = Games::find([1]);

$players = $game->players()->get();
IGP
  • 14,160
  • 4
  • 26
  • 43
1

The normal usage for find() is to pass an id, and it will return a model instance for that id. However, if you pass in an array, or an object that implements \Illuminate\Contracts\Support\Arrayable, it will return a Collection of all the found instances.

Your controller code is this:

$game = Games::find($game);

If the $game value passed into find() here is an array, it will return a Collection of all the models found using the ids in the array.

Another sneaky issue here is if the $game value passed into find() here is a model instance. In this case, this statement will return a Collection, because models implement the Arrayable contract mentioned above.

So, when you call find() and pass in a model, it will call toArray() on that model, attempt to find records for every value returned in the array, and return a Collection of all the records found.

In either case, $game is now a Collection, and you'll get an error when you attempt to call $game->players(), since the players() method does not exist on collections.

patricus
  • 59,488
  • 15
  • 143
  • 145