This isn't really a job for the Element API plugin. You can accomplish what you want much easier by just creating a plain ol' Twig template (e.g. templates/updates.json
) that pulls the three latest updated entries from each section, and returns the entries' dateUpdated
values as JSON:
{% header "Content-Type: application/json" %}
{%- spaceless -%}
{% set sections = ['themes', 'videos', 'screensavers'] %}
{% set entries = [] %}
{% for section in sections %}
{% set entry = craft.entries.section(section).order('dateUpdated desc').limit(1).first() %}
{% set entries = entry ? entries|merge([entry]) : entries %}
{% endfor %}
{
{%- for entry in entries -%}
"{{ entry.section.handle }}":"{{ entry.dateUpdated }}"{% if not loop.last %},{% endif %}
{%- endfor -%}
}
{%- endspaceless -%}
The above would render a JSON payload exactly like the one you have in your example.
If you really want to use Element API for some reason, you can get pretty close to what you want (but not quite). Here's why it's difficult to do, though:
For one, the transformer
property function operates on a single entry at the time, which is a problem in terms of your desired payload.
Second, with Element API you don't have full control of the JSON format the plugin returns – so you'll never get the payload to look exactly like you want (the actual data will be wrapped in a data
property).
Third and most importantly, an Element API endpoint requires a single query (or actually, a single ElementCriteriaModel) to pull your elements. Unfortunately, it isn't possible to tell an ElementCriteriaModel to return 1 entry from each section – notice that even in the template example above, there's actually three queries – one for each section (they're just wrapped in a for
loop to keep the code small and DRY).
So basically, you'll need to "trick" Element API to return something similar to your example JSON.
First, since you can't use a single ElementCriteriaModel to query your 3 latest entries, you'll actually need three of those suckers. The Element API plugin gives you one, but you'll need to create the other two inside the transformer
function – you just need to ensure that Element API actually runs that function, and only runs it once, by pulling a single entry (in other words; you'll need a limit => 1
for your endpoint's criteria
). It makes sense to have the endpoint pull one of the three entries you need, so you'll avoid a redundant database query. Then, you'll have to pull the other two entries "manually". Finally, for the return value you can return an array similar to what you have in your example:
'updates.json' => [
'elementType' => 'Entry',
'paginate' => false,
'criteria' => ['section' => 'themes', 'order' => 'dateUpdated desc', 'limit' => 1],
'transformer' => function(EntryModel $entry) {
$themesEntry = $entry;
$videosEntry = craft()->elements->getCriteria(ElementType::Entry, [
'section' => 'videos',
'order' => 'dateUpdated desc',
'limit' => 1
])->first();
$screensaversEntry = craft()->elements->getCriteria(ElementType::Entry, [
'section' => 'screensavers',
'order' => 'dateUpdated desc',
'limit' => 1
])->first();
return [
'themes' => date('Y-m-d', $themesEntry->dateUpdated->getTimestamp()),
'videos' => date('Y-m-d', $videosEntry->dateUpdated->getTimestamp()),
'screensavers' => date('Y-m-d', $screensaversEntry->dateUpdated->getTimestamp()),
];
}
]
The above would return a JSON payload looking something like this:
{"data":[{"themes":"2016-02-23","videos":"2016-08-23","screensavers":"2016-07-16"}]}