Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting belongsTo in Laravel to Eloquent Model #32

Open
b-t-927 opened this issue Mar 15, 2022 · 7 comments · May be fixed by #35
Open

Setting belongsTo in Laravel to Eloquent Model #32

b-t-927 opened this issue Mar 15, 2022 · 7 comments · May be fixed by #35
Labels
documentation Improvements or additions to documentation

Comments

@b-t-927
Copy link

b-t-927 commented Mar 15, 2022

After updating an existing model in laravel to make use of ApiWrapper, I'm unable to load any belongsTo relationships from the model object that gets created. Trying to access them causes the following exception:

TypeError: Cristal\ApiWrapper\Relations\BelongsTo::__construct(): Argument #2 ($related) must be of type Cristal\ApiWrapper\Model, App\Models\User given

Is it possible to have a bridged model belong to an existing Eloquent model and I'm just missing something configuration-wise?

@TZK-
Copy link
Member

TZK- commented Mar 15, 2022

Hello,

When you need to define relations between an API Model and a regular Eloquent model, you need to use the trait Cristal\ApiWrapper\Bridges\Laravel\HasApiRelations

This trait will override the relation methods (belongsTo, hasMany etc.), to support both API and Eloquent Models.

The documentation about relations is not ready yet (actually not really the time to do it), but I keep it in mind.

Let me know if you want more precision,

@TZK- TZK- added the documentation Improvements or additions to documentation label Mar 15, 2022
@b-t-927
Copy link
Author

b-t-927 commented Mar 15, 2022

Thanks for the response, I figured it involved the traits, but I had some trouble getting them going.

Since the error relates to the belongsTo method I'd assume I'd want to apply the HasApiRelations trait, though given the names of it and HasEloquentRelations I'm not too sure?

Either way I've tried various combinations of using those traits to both the Eloquent and API model classes but it doesn't even seem to be making much difference as trying to access the relationship on the API model still seems to be trying to call Cristal\ApiWrapper\Relations\BelongsTo.

I assume it's just me doing something wrong, but I'm not entirely sure what at this point!

@TZK-
Copy link
Member

TZK- commented Mar 15, 2022

Can you provide the code of your Eloquent model and your API model and how your are calling the relation through your model just to be sure there are no understanding problems from my side ?

@b-t-927
Copy link
Author

b-t-927 commented Mar 15, 2022

Sure, they're pretty basic so far but my API Model is:

<?php

namespace App\Models;

use Cristal\ApiWrapper\Bridges\Laravel\Model;

class Site extends Model
{
    protected $primaryKey = 'uuid';
    protected $keyType = 'uuid';
    protected $entity = 'site';
    public $incrementing = false;

    public function owner()
    {
        return $this->belongsTo('App\Models\User');
    }
}

My Eloquent model is pretty much just the standard User model:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Cristal\ApiWrapper\Bridges\Laravel\HasApiRelations;

class User extends Authenticatable
{
    use HasApiRelations, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'email', 'password', 'api_token', 'username'
    ];

    public function sites()
    {
        return $this->hasMany('App\Models\Site', 'id', 'owner_id');
    }
}

As for the calling pretty much the standard approach, here's the output from testing in artisan tinker:

>>> $site = Site::find('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
[!] Aliasing 'Site' to 'App\Models\Site' for this Tinker session.
=> App\Models\Site {#3858
     +incrementing: false,
     +exists: true,
     +wasRecentlyCreated: false,
   }
>>> $site->owner
TypeError: Cristal\ApiWrapper\Relations\BelongsTo::__construct(): Argument #2 ($related) must be of type Cristal\ApiWrapper\Model, App\Models\User given

The reverse, trying to access the sites that belong to the user works fine. I can also see I've not mentioned, but this is with Laravel 8.83.4 and PHP 8.0.3.

@TZK-
Copy link
Member

TZK- commented Mar 18, 2022

Ok, indeed we haven't implemented belongsTo relations from an API Model to an Eloquent Model.

I think you can turn into a hasOne relation instead. Can you confirm it works with that ?

I do not have enough time to dig into the issue at the moment, but I keep it in mind.

You can also try to open a pull request if you want 😊

@b-t-927 b-t-927 linked a pull request Mar 21, 2022 that will close this issue
@b-t-927
Copy link
Author

b-t-927 commented Mar 21, 2022

Sure, I've just made a PR for a quick and dirty attempt. I'm going to put it through some more testing internally first

@MiloDBD
Copy link

MiloDBD commented Sep 19, 2023

Its been a while, I'm also looking for this functionality... can I help?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants