statamic / ideas

💡Discussions on ideas and feature requests for Statamic
https://statamic.dev
30 stars 1 forks source link

Ability to "select" the relationship fields that get augmented #1056

Open duncanmcclean opened 9 months ago

duncanmcclean commented 9 months ago

I've just come up against a scenario when using the toAugmentedArray method where we'd like to "select" particular fields on a related entry to be augmented instead of Statamic augmenting all of them (which gets slow if you have lots of fields, like we do).

Use Case

In our case, we have a Live Availability page returning all of the units currently available for rent. Each of these unit entries are related to a location entry which holds information about the address, amenities, local places of interest etc.

Once we've done all of our query work, the final thing we do is augment each of the unit entries. Here's a really simple example of what we're doing:

Entry::query()
    ->where('collection', 'units')
    ->where('location', '459f2c54-a51e-4d03-8c5a-b27cbb0be954')
    ->get()
    ->map->toAugmentedArray([
        'title',
        'location',
    ])
    ->map(fn ($entry) => collect($entry)->map->value()->toArray())
    ->all();

However, in doing some performance troubleshooting, I've realised that when we augment the location field, it's adding multiple seconds onto the response time.

We only use 2 fields from the location in this use case: the title and the slug, so there's not much point in everything else being augmented when it's not needed.

Possible Solution

Ideally, Statamic's toAugmentedArray method would have a way to select the columns you want to be augmented. Maybe something similar to what you can do with the ->with() method on the Eloquent query builder?

Entry::query()
    ->where('collection', 'units')
    ->where('location', '459f2c54-a51e-4d03-8c5a-b27cbb0be954')
    ->get()
    ->map->toAugmentedArray([
        'title',
        'location:title,slug', // This is the bit I've changed
    ])
    ->map(fn ($entry) => collect($entry)->map->value()->toArray())
    ->all();

Implementation

I've had a look to see what it would take to make this possible... by the looks of things, we'd need to pass another parameter to the fieldtype augment methods, then pass them through to the query builder so when the ->get() method is called on the query, it uses the selected columns. However, I don't know if that might break stuff for custom fieldtypes?

If you're interested, here are my changes thus far and here is my test site (go to /glasgow-posts).

Workaround

For the moment, I've managed to workaround this by creating a computed value for location_title and location_slug that looks up the entry and grabs the title/slug without any augmentation.

jasonvarga commented 9 months ago

Pass an array of fields to get().

->get(['title', 'location'])
duncanmcclean commented 9 months ago

Will that work since it's fields from the location relationship I want to select by, not fields on the unit entries?

jasonvarga commented 9 months ago

Sorry I misunderstood. 😊