Home > Back-end >  Re-arrange a CakePHP JSON response on object prior to render
Re-arrange a CakePHP JSON response on object prior to render

Time:10-26

I am working on an CakePHP REST/CRUD based API. It uses $routes->setExtensions(['json']); within /config/routes.php to make the it's responses into json objects.

I am working with several objects that have complex schema's that I need to pre-process prior to to submitting to the CakeORM, in order to simplify the API integration for the end user.

For instance the following is the json blob that would be needed to be patched to the ORM using $this->ImportSettings->patchEntity($importSetting, $requestData[2]):

    {
        "id": 2,
        "generic_setting": "Hello World",
        "import_source_google_setting": null,
        "import_source_csv_ordered_setting": null,
        "import_source_csv_headed_setting": {
            "id": 1,
            "import_settings_id": 2,
            "delimiterId": 1 
        },
        "import_destination_user_setting": null,
        "import_destination_asset_setting": {
            "id": 2,
            "import_settings_id": 2,
            "defaultValueId": 1 
        }
    }

There can be one of many sources and one of many designation settings defined on an import setting. To simplify this for the API user I am allowing them to submit, the following:

    {
        "id": 2,
        "generic_setting": "Hello World",
        "import_source_setting": {
            "id": 1,
            "import_settings_id": 2,
            "delimiterId": 1 
        },
        "import_destination_setting": {
            "id": 2,
            "import_settings_id": 2,
            "defaultValueId": 1 
        }
    }

I have written code into an event listener on beforeMarshal for ImportSesttings that is able to tell if the index "import_source_setting" belongs in in the tables "import_source_csv_headed_setting", "import_source_csv_ordered_setting" or "import_source_google_setting" and likewise with asset and user settings going into "import_destination_setting".

This works well for processing a re-organizing data in a request before it enters the ORM. However I would like to do the same thing now with the data before it is displayed, so the API user does not need to look at the addtional source and destination settings.

I have accomplished this through the use of middleware in a similar use case in another part of the system. However the middleware seems to be made to attach to routes, my uses seems more like something that should be tied to the model life cycle so it runs whenever an import settings is returned and properly modifies the output, even when nested.

Given what I am looking for, what part of Cake should I place this logic that re-organizes the json response on the ORM query result for a table in? Can your point me to documentation on this?

CodePudding user response:

I came across an answer for this in another forum using CakePHP's calculated fields. It looks like the formatResults() function can be attached to a query with a callback to re-organize the results after the query is ran. I went ahead and attached it to the query in the beforeFind() event, which seems to work.

See example below:

<?php

class ImportSettingsListener implements Cake\Event\EventListenerInterface
{
    public function implementedEvents(): array
    {
        return [
            'Model.beforeFind' => 'generateQuery',
        ];
    }

    public function generateQuery(Event $event, Query $query, ArrayObject $options, bool $primary): void
    {
        $query->formatResults(function (CollectionInterface $results) {
            return $results->map(function ($setting) {
                // Re-format $setting here
                return $setting;
            });
        });
    }
}
  • Related