Skip to content

Conversation

@caseydwyer
Copy link
Contributor

@caseydwyer caseydwyer commented Nov 19, 2025

This PR adds functionality to the Relationships class, allowing for registration of custom save-methods. The core Runway features provide 95% of what's needed for custom relationships, but an error is thrown when using a third-party class since the only match cases are native HasMany and BelongsToMany eloquent relationships. We're just adding a default/fallback, to provide devs with an option for registering their own save callback.

A good example use-case would be the relationship classes found in the Eloquent JSON Relations package, where a belongs-to-many equivalent can exist in a JSON column. Here's how this could be used, from within a service provider:

use Staudenmeir\EloquentJsonRelations\Relations\BelongsToJson;

Relationships::registerCustomSaveMethod(
    BelongsToJson::class,
    fn ($field, $relationship, $values) => $relationship->sync($values)->save()
);

And then the corresponding field from the resource's blueprint:

-
  handle: hiring_manager_roles
  field:
    mode: select
    resource: staff_role
    relationship_name: hiringManagerRoles
    type: has_many
    display: 'Hiring Manager Roles'

Obviously an unsolicited feature request, but would be a big improvement on super-dynamic projects that leverage JSON columns in multiple places. Please let me know if there's anything I can do to improve this (general updates, along with tests, doc updates, etc.) and I'll make it happen. Thanks for considering this!

Copy link
Member

@duncanmcclean duncanmcclean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea!

Although, can we use a hook instead of our own saveCustomRelationship method?

@caseydwyer
Copy link
Contributor Author

can we use a hook instead of our own saveCustomRelationship method?

Ooh, yeah—good call on that! Tbh, I did not know you could use hooks like that, so let me know if this isn't what you had in mind. This updated approach of course requires different usage, something like this I think:

Relationships::hook('saveCustomRelationship', function ($payload, $next) {
    [
        'relationship' => $relationship,
        'values' => $values,
    ] = $payload;

    if(get_class($relationship) === BelongsToJson::class){
        $relationship->sync($values)->save();
    }

    return $next($payload);
});

@duncanmcclean
Copy link
Member

That's perfect! I'll review this properly next week. 🙂

Copy link
Member

@duncanmcclean duncanmcclean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - thanks!

@duncanmcclean duncanmcclean merged commit 70434a3 into statamic-rad-pack:8.x Nov 24, 2025
18 checks passed
@github-actions
Copy link

Released as part of v8.8.0.

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

Successfully merging this pull request may close these issues.

2 participants