marcreichel/igdb-laravel

Error when setting up relationships between IGDBLaravel\Models and regular Models

Closed this issue ยท 6 comments

Hello,

I'm trying to setup a basic Many-To-Many relationships between two models, one is "Game" from IGDBLaravel\Models and the other one is "User" from App\Models.
I set up the relationship as a property of User, like this:

    use MarcReichel\IGDBLaravel\Models\Game;

    public function games()
    {
        return $this->belongsToMany(Game::class, 'game_user', 'user_id', 'game_id');
    }

I also created an intermediate table in the database, here's the migration:

    public function up()
    {
        Schema::create('game_user', function (Blueprint $table) {
            $table->foreignId('user_id');
            $table->foreignId('game_id');
        });
    }

I populated the pivot table with a simple test row, user_id = 1 and game_id = 1905, I should get Fortnite when calling the property from User model. I try calling it in the controller like this:

$user = User::find(1);
$games = $user->games;

This should work in Many-To-Many relationship in Laravel using Eloquent, but unfortunately is not working in this case, it's returning this error:

Call to undefined method MarcReichel\IGDBLaravel\Models\Game::getConnectionName()

Am I doing something wrong?
Or is it impossible to use the wrapper like this, since they are two different kind of models?
How should I implement a relationship like this one if eloquent Models are off the table?

Many thanks in advance!

@lordbel89 Hi there,

what you're trying to achieve is not possible directly. You need to see this package as an API-Wrapper where each endpoint is mapped to a model to have an Eloquent-like query syntax. The models from this package aren't actual Eloquent models tho.

What you can do is create your own Game (Eloquent) model with its associated database table and use this package to populate your database/eloquent model. And then you can have your model relationships as usual between your user and game models.

Hope this helps pushing you into the right direction :) Let me know if you need further help.

@marcreichel Hello,

Many thanks for your explanation! I was under the impression that it was really not the same between the two models.
That being said, I'll probably follow your advice and try to copy the structure of IGDB and create models for my database, so I can create relationships easily.

About populating my local database with data from IGDB, how do you suggest I can approach it? Maybe scrape everything the first time and then keep synch using webhooks?

Many thanks again for your advice!

@lordbel89

I'm happy to help ๐Ÿ™‚

It more or less depends on your use case. You can also just fetch the game information once or update it every month (or so) using a cronjob or keep everything in sync using webhooks. It really depends on what you're trying to achieve.

@marcreichel

I'm still learning Laravel, and using your wonderful wrapper for a personal project. I'm trying to code a "Backlog game website", where me and my friends can wishlist games, give them rating, put them in different kind of list (Bought, Played, Finished, Dropped and so on), and review them.

I coded an interface for the wrapper with no issues, using it to easily display game detail data, and have nice collection pages like "Latest releases", "Popular right now", "Releases by console", getting all the game data from the Wrapper! But now I understand that I can't directly intertwine the data from the Wrapper with the data from my database.

Just looking for your advice on how would you achieve this kind of functionalities, and I'll close the issue (wich wasn't even an issue, it's working as intended!) and stop bothering you, many thanks again in advance :)

@lordbel89 Then first: Welcome to the wonderful world of Laravel ๐ŸŽ‰

Yes, it's always a good idea to persist the data of the API in your own database and use the data from there. Not only to have features like relationships etc. Just think about what happens to your app if IGDB might have a downtime for example. Your app could not be used as well.

So what you can do is the following (all untested and just pseudo-code-ish just to give you an idea how it could work in general):

  1. Create an Eloquent model for the game like so:
    php artisan make:model Game -m
  2. Fill the migration file with the database structure you need in your application.
    // ...
    Schema::create('games', function (Blueprint $table) {
       $table->unsignedBigInteger('id')->primary();
       $table->bigInteger('igdb_id');
       $table->string('title');
       // ...
    });
    // ...
  3. Create the required relationships (like many-to-many between user and game).
  4. In a controller request the game data from the API:
    use App\Models\Game;
    use MarcReichel\IGDBLaravel\Models\Game as IGDBGame;
    
    public function store(Request $request)
    {
        $igdbGame = IGDBGame::where(/* your query */)->first();
        
        $game = Game::updateOrCreate([
            'igdb_id' => $igdbGame->id,
        ],[
            'title' => $igdbGame->title,
        ]);
    
        Auth::user()->games()->attach($game);
    }
  5. (Optional) Set up a webhook (following the docs here) to keep the game data in your database in sync with IGDB.

Don't worry ๐Ÿ™‚ I'm here to help. If you need any further help, just let me know ๐Ÿ™‚

@marcreichel Many thanks for your suggestion, it definitely looks super slick! I was kinda wondering how to keep the data in synch with the same IDs, it never occurred to me that I can have a field "igdb_id" in my model!

Your suggestion looks slick - using UpdateOrCreate in the controller I can make sure to always have a copy of the fresh data in my database whenever the game data needs to be stored, and I can make use of Eloquent Models and Relationships to easily display the data in the frontend.

Thank you again for your patience and your wonderful wrapper! Getting the data from IGDB without having to worry about Authentication and without scaffolding the whole API is so good! :)