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

[Feature] API endpoint to fetch items of multiple models at once #195

Open
BFS-JWesseler opened this issue Jun 27, 2024 · 1 comment
Open

Comments

@BFS-JWesseler
Copy link

BFS-JWesseler commented Jun 27, 2024

API endpoint to fetch items of multiple models at once

Currently, we are facing the issue that we have around 40-50 models which require as many singular HTTP requests. It would be nice if we could fetch all of the items of multiple models with the same filter settings at once. It also does not need to be optimized on the data structure, basically can be done with a loop and adding the models to a JSON array which then contains the items of the respective models as usual.

Current it looks like:

api/content/items/<model1>?filter=<filter>
api/content/items/<model2>?filter=<filter>
api/content/items/<model3>?filter=<filter>

The idea would be to have something like:
api/content/multiple-items?models=[<model1>,<model2>,...]&filter=<filter>

You could also add an array to the filters for something like (so that you can have filters per model if needed - even if we don't need it):
api/content/multiple-items?models=[<model1>,<model2>,...]&filters=[<filter1>,<filter2>,...]

Or something similar. Anyway, that would be awesome to have and would speed up our initialization time by a lot. The easiest solution will suffice, as long as we don't need to make 40-50 HTTP requests for fetching the items of the different models with the same filter.
It would be greatly appreciated.

@aheinze
Copy link
Collaborator

aheinze commented Jun 28, 2024

Hi 👋

You can already do this with a custom api endpoint.

Example

Create the following file: config/api/batch-content-items.php

With the following contents:

<?php

$batch = $this->param('batch', null);

if (!$batch) {
    return $this->stop(412);
}

try {
    $batch = json5_decode($batch, true);
} catch(\Throwable $e) {
    $this->stop(['error' => "<batch> is not valid json"], 412);
}

$return = [];
$content = $this->module('content');

$userRole = $this->helper('auth')->getUser('role');

foreach ($batch as $model => $opts) {

    if (!$content->model($model) || !$this->helper('acl')->isAllowed("content/{$model}/read", $userRole)) {
        continue;
    }

    $options = [];
    $process = ['locale' => $opts['locale'] ?? $this->param('locale', 'default')];

    if (isset($opts['filter'])) $options['filter'] = $opts['filter'];
    if (isset($opts['sort'])) $options['sort'] = $opts['sort'];
    if (isset($opts['fields'])) $options['fields'] = $opts['fields'];
    if (isset($opts['limit'])) $options['limit'] = $opts['limit'];
    if (isset($opts['skip'])) $options['skip'] = $opts['skip'];

    if (isset($opts['populate'])) {
        $process['populate'] = $opts['populate'];
        $process['user'] = $this->helper('auth')->getUser();
    }

    if (!isset($options['filter']) || !is_array($options['filter'])) {
        $options['filter'] = [];
    }

    // only published items
    $options['filter']['_state'] = 1;

    $return[$model] = $content->items($model, $options, $process);
}

return $return;

Now you can request the following endpoint:

/api/batch-content-items?batch={model1:{filter:{...}}, model2:{filter:{...}}, ...}

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

2 participants