3

I'm trying to integrate the ElementAPI plugin into my site. Essentially, I need to output all of the assets within the website into a JSON file that I can link to in the load manifest of PreloadJS. If you read the docs here, you'll see that the images can be loaded from an external JSON file.

Here's what I've been working with so far:

<?php
namespace Craft;

return [
    'endpoints' => [
        'assets.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'news'],
            'transformer' => function (EntryModel $entry) {
$images = [];
        foreach ($entry->featuredImage as $image) {
        $images[] = $image->url;
        }
                return [
                    'image' => $entry->image
                    'jsonUrl' => UrlHelper::getUrl("assets/data.json")
                ];
            },
        ]
    ]
];

So, to sum up, what I'm needing to do is build an API that will get a list of all the assets used in my site and output them into a JSON file that I can link to in a JS file as part of the PreloarJs plugin. This would make my preloader dynamic and allow me to keep my javascript external, rather than getting the assets inline, which I have been doing.

Thanks!

5

Something like the following should work:

// elementapi.php
return [
    'endpoints' => [
        'assets.json' => [
            'paginate' => false,
            'elementType' => ElementType::Asset,
            'criteria' => [
                'limit' => null,
            ],
            'transformer' => function(AssetFileModel $asset) {
                // Set `generateTransformsBeforePageLoad` to `true` to have Craft generate transforms at runtime
                craft()->config->set('generateTransformsBeforePageLoad', true);
                return [
                    'title' => $asset->title,
                    'url' => $asset->url,
                    'thumb' => $asset->getUrl(['width' => 100, 'height' => 100]),
                ];
            },
       ],
    ]
];

One small gotcha: By default, Element API will paginate results. To avoid that, you can add a 'paginate' => false, parameter to your endpoint.

Another small gotcha: If you want to return transformed Assets (e.g. a thumbnail version), you can pass a named or inline (array) transform to $asset->getUrl(), but you'll need to set the generateTransformsBeforePageLoad config setting to true at runtime in order to have Craft actually generate the transforms when the endpoint is requested.

Finally: Depending on the number of Assets and Entries, you might see some performance issues with this method (especially if you're going to include transforms and don't paginate the results), so it'll probably be a good idea to cache the assets.json output in some way.

  • Thanks! And can I link to assets.json in another file? – Jesse Winton Jul 11 '16 at 16:21
  • Not sure I know what you mean by "link to in a file" - the URL to the Element API endpoint would be domain.com/assets.json, and it'll print a JSON object with all your Assets. For your purposes, you should probably cache the output to a static file, though. – Mats Mikkel Rummelhoff Jul 11 '16 at 16:27
  • For some reason, I get a 500 Internal Server error saying that assets.json doesn't exist. Also, I realized this code is only getting assets in the featuredImage field. Is there a way to modify this to get all assets in the website? – Jesse Winton Jul 11 '16 at 18:06
  • Just edited the answer; the example code will now pull all Assets in your site; not just the ones related to certain entries. Don't know about the 500 error, sounds weird & the code works fine on my end. Did you put the elementapi.php file in your config folder, alongside general.php? Did you activate the plugin? – Mats Mikkel Rummelhoff Jul 11 '16 at 18:13
  • 1
    As for Preload.js; I think it's able to load external manifests, but you might need to give it the full URL, i.e. loadManifest('http://yourwebsite.com/assets.json') or just loadManifest('/assets.json'). Another issue is whether the Element API payload adheres to the Preload.js manifest format – it probably doesn't, so you probably need to fetch it with AJAX (jQuery) first, loop through it and create a Preload.js compliant manifest, and finally load that. – Mats Mikkel Rummelhoff Jul 11 '16 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.