I'm running the ElementAPI but would like to take advantage of some functionality provided by another plugin, to return these results in the API. Is this possible? Should all functions available in the main templates be available to the ElementAPI?

To be specific about what I'm trying to achieve--I'm trying to access the Imager plugin to handle optimised transformations of an uploaded image. Here's how the code looks in a regular Twig template

{% set transformedImage = craft.imager.transformImage(image, { width: 200 }) %}
<img src="{{ transformedImage.url }}">

And my attempt to do this inside elementapi.php is:

$sizerOptions = array( 'width' => '202' )
transformedImage = craft()->imager->transformImage( $asset->url, $sizerOptions );

My PHP is not brilliant so I may just be doing something silly here, but wondering if it's my fault, or if I'm attempting to do something impossible!

3 Answers 3


Your approach is technically correct – the problem is that craft()->imager->transformImage() requires two additional parameters; $transformDefaults and $configOverrides.

You can read more about these parameters and the transformImage method in the plugin's official docs, but it's not super important. The two parameters can actually be null, which means the following should work:

$sizerOptions = array('width' => 202);
$transformedImage = craft()->imager->transformImage($asset, $sizerOptions, null, null);

Note that while Imager does work with URLs, if you do have an AssetFileModel (i.e. $asset) it's actually better to feed that to transformImage() because then Imager will handle automatic cache breaking etc. for you (e.g. if you replace the image in Craft later on) – so my advice is to use transformImage($asset), not transformImage($asset->url), whenever possible.

Finally, in case you're wondering why the below works for templates:

{% set transformedImage = craft.imager.transformImage(image, transform) %}

...when you need the additional two parameters when you do the same thing in PHP, here's a quick explanation of what's going on:

Plugins in Craft are made up of several different components – among them, Services and Variables.

You can think of Services and Variables as two different APIs for a plugin – one is only made available to PHP (Services) and the other is only made available to Twig/templates (Variables).

Craft makes plugin Services available in PHP by instantiating them and adding them to the global craft() object in the format craft()->serviceName. For many plugins, there'll only be a single service, usually named after the plugin itself (e.g. ImagerService, which is mapped to craft()->imager). There can be several though, e.g. Imager_AnotherService, which would be mapped to craft()->imager_another.

Unlike Services, plugins can only have a single Variables class, which is always named after the plugin (e.g. PluginNameVariable) and mapped to craft.pluginName. In Imager's case, this means that the ImagerVariable is mapped to craft.imager in Twig.

Whenever you call craft.imager.transformImage() in a template, you're actually interacting with a Variable class – in this case, ImagerVariable. When you call craft()->imager->transformImage() in PHP, you're interacting with the ImagerService class.

The fact that the ImagerVariable and ImagerService both have a method called transformImage is a common design pattern in Craft, where variable classes are used to "wrap" Services, in order to expose the latter for use in templates. Often (and this is true for Imager, as well), the Variable methods do little more than to call their namesake Service methods. Using the same names for Variable and Service methods isn't a requirement, though – just a "best practice" to ensure consistent plugin APIs for templates and PHP. Imager's author could've opted to call the Variable method transform, doTransform, transformy or basically anything else.

Finally – as I mentioned, Imager's Variable method transformImage basically just wraps the ImagerService->transformImage method – but with one important difference: The Variable method makes the two additional parameters ($transformDefaults and $configOverrides) optional. This is why you don't have to declare them when you use Imager in a template, but you do have to define them when you use it in PHP.

A fun trick is that while Craft doesn't expose Template Variable classes to PHP out of the box, there's nothing preventing you from using them "manually". For example, say you prefer the Imager's Template Variable API over its Service API; here's how you can use the Variable methods wherever you want in your PHP:

$imager = new ImagerVariable();

$transformedImage = $imager->transformImage($asset, $sizerOptions);
  • Hey, I just wanted to say that this is one of the best answers I've ever had the pleasure to receive on SO! I was absolutely stunned when I read through it. I'd actually tried passing the 2 extra null parameters into the function at some point but I can only think that I must have had a mistake elsewhere when I tried that. This sorted me out perfectly and I really appreciate the thorough explanation! Thanks man!
    – user4672
    Feb 5, 2016 at 11:11
  • Whoa, that's awesome to hear @JonLay – thanks! Made my weekend :) Feb 5, 2016 at 11:12
  • Love the Craft::import trick. Unfortunately no longer available on Craft 3. Not sure if it was renamed or moved entirely, I spent some time looking with no luck.
    – Jameal G
    Jul 28, 2020 at 18:50

You cannot say for sure how the PHP API of a Craft plugin has to be by just looking at the Twig code. You have to reverse engineer it. If the Twig function you're calling from the template starts with craft.pluginHandle, like in this case:

{% set var = craft.imager.transformImage() %}

you're dealing with a plugin's template variable. If the function isn't namespaced like this or if you apply it to a Twig value with the pipe character, it is a Twig extension.

{% set var = myTwigFunction() %} or
{% set var = value|myTwigFilter %}

Ok, so I now looked up that transformImage function in imager/variables/imagerVariable.php. I already expected this, because you're lucky and Andre is an excellent developer, but you can see it is basically passing all the parameters to a plugin service craft()->imager->transformImage(). Have a look at that specific service class imager/services/ImagerService.php. All its public methods are accessible from anywhere in your PHP code, it's the plugin's API. So what you have posted is actually very close to what you need, you just have some smaller syntax errors and if you take a closer look at the method's declaration, you'll see that it expects 4 parameters.

public function transformImage($image, $transform, $transformDefaults, $configOverrides) { }

Using the template variable you only need to set the first two of them and sets a default for the latter. But as the service method doesn't do this for you (in this case), you have to set them.

I haven't tested this, and might be missing something, but this should be at least a good starting point to get it working from another plugin like the Element API:

$sizerOptions = array('width' => 202);
$transformedImage = craft()->imager->transformImage($asset->url, $sizerOptions, null, null);
  • Thanks for the answer! You were right, but Mats got there first with his quite amazingly details reply. Appreciate the help, however! :)
    – user4672
    Feb 5, 2016 at 11:12

I came across this question in a search while trying to access Imager in an Element API transformer function in Craft 3. Things have changed a bit so I thought I would post some details in case anyone else is trying to do the same thing.

First thing, you need to make Imager available to your Element API functions like this:

use aelvan\imager\variables\ImagerVariable;

Then, within your transformer, you can do something like this:

'transformer' => function(Entry $entry) {
    $imager = new ImagerVariable();
    $photos = [];

    foreach ($entry->thumbnailImage.all() as $image) {
        $imageOptions = array(
            'width' => 300,
            'height' => 300,
            'mode' => 'crop',
            'position' =>  $image->getFocalPoint(),

        $transformedImage = $imager->transformImage($image, $imageOptions);
        $photos[] = $transformedImage->getUrl();

    return [
        'id' => $entry->id,
        'thumbnail' => $photos
  • I suggest you to avoid doing things like new ImagerVariable(); Mats Mikkel Rummelhoff made the difference between variables and services really clear and when you take a look at the plugin, you'll see that your function is just a wrapper for Plugin::$plugin->imager->transformImage($file, $transform, $transformDefaults, $configOverrides); You should access the plugin directly and not via Variable Apr 19, 2018 at 6:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.