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

How to define a morphTo relationship? #53

Open
nelson6e65 opened this issue May 18, 2024 · 1 comment
Open

How to define a morphTo relationship? #53

nelson6e65 opened this issue May 18, 2024 · 1 comment

Comments

@nelson6e65
Copy link

As its polymorphic nature, I can't know in advance what resource type it will be.

class AddressResource extends JsonApiResource
{
    public $attributes = [
        'label',
        'geo_point',
    ];

    public $relationships = [
        'owner' => UserResource::class, // But also can be TeamResource, RestaurantResource, etc
    ];
}

Is there a way to check loaded $resource->owner->getTable() to guest the corresponding type?
Or maybe a trait included in my model with the method getJsonApiResouce(): $this->resource->owner->getJsonApiResource()

class User extends Model IHasJsonApiResource
{
    use HasFactory;

    /**
     * @return class-string<JsonApiResource>
     */
    public function getJsonApiResouce(): string
    {
        return UserResource::class;
    }
    
}

Or a similar way of doing it, as User::factory() works.

@nelson6e65
Copy link
Author

I "solved" it by using this in my AppServiceProvider:

JsonApiResource::guessRelationshipResourceUsing(function (string $relationship, JsonApiResource $jsonApiResource) {
    if (!$jsonApiResource->resource instanceof EloquentModel) {
        return null;
    }

    // TODO: Parametrizar estos namespaces.
    $modelsNamespace    = 'App\\Models\\';
    $resourcesNamespace = 'App\\Http\\Resources\\JsonApi\\';

    // How can I detect the underlying model class of an Eloquent relationship? Is this OK?
    $relatedModelClass = get_class($jsonApiResource->resource->{$relationship}()->getModel());

    // This will work only for Models following that structure.
    $relatedResourceClass = str_replace($modelsNamespace, $resourcesNamespace, $relatedModelClass) . 'Resource';

    if (!class_exists($relatedResourceClass)) {
        throw new \BadMethodCallException(
            "Resource class `{$relatedResourceClass}` not found for relationship `{$relationship}`."
        );
    }

    return $relatedResourceClass;
});

With this resources' resolver, it will guest the resource class by relationship model's class instead of relationship name. But I'm not sure if is it consequent enough for all kind of relationships.

App\Models\User <=> App\Http\Resources\JsonApi\UserResource

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

No branches or pull requests

1 participant