# Automatic generation of transforms
Transforms has to be generated at some point, they don't just appear like unicorns because you wanted them to (bummer, we know!). Generating transforms is a resource heavy process, and doing it runtime when a page is requested, can be brutal.
This new feature in Imager X aims to mitigate some of the pain of generating transforms. With automatic generation of transforms you can create transforms when an asset is uploaded or when an element is saved. Also, you can use console commands and element actions to run the auto generation any time you want.
TIP
All automatic generation of transforms is done via queue jobs, to keep delays from happening when assets are uploaded, or elements are saved. Please note that if you're running your queue via a cron job, there may be a delay before the transforms are generated, which could result in delays for front end users. We highly recommend running a daemon that listens for new jobs instead, if at all possible.
# Setting it up
To set up automatic generation, create a config file in your config folder
named imager-x-generate.php
. All configuration settings can be found in
the configuration section,
but let's ease in with a simple example.
As a start, let's say we want all images uploaded to our volume with
handle employeeImages
, to have two named transform
called employeeThumbnail
and employeePoster
be auto-generated:
<?php
return [
'volumes' => [
'employeeImages' => ['employeeThumbnailTransform', 'employeePoster'],
]
];
That was easy enough. Now, let's say we have another volume, a generic one with handle images
,
where alot of our other images go. We have some frequetly used transforms
that we chuck in there:
<?php
return [
'volumes' => [
'employeeImages' => ['employeeThumbnail', 'employeePoster'],
'images' => ['defaultHeroImage', 'listImage', 'eventHeroImage', 'seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
]
];
That's good and all, but you quickly realize that only a few of the transforms generated will ever be used, since images in this volume is used across many sections and fields.
The eventHeroImage
transform will only ever be used for images that's added
to the heroImage
field in the Events section. This is a good candidate for
using the elements
generate setting, like this:
<?php
return [
'volumes' => [
'employeeImages' => ['employeeThumbnail', 'employeePoster'],
'images' => ['defaultHeroImage', 'listImage', 'seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
],
'elements' => [
[
'elementType' => \craft\elements\Entry::class,
'criteria' => [
'section' => 'events',
],
'fields' => ['heroImage'],
'transforms' => ['eventHeroImage']
]
],
];
TIP
The criteria parameter is passed directly to the element query, and takes exactly the same parameters as a standard Craft element query.
In fact, the defaultHeroImage
transform is also used in a limited number of
sections and fields, so let's split that out into elements too:
<?php
return [
'volumes' => [
'employeeImages' => ['employeeThumbnail', 'employeePoster'],
'images' => ['listImage', 'seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
],
'elements' => [
[
'elementType' => \craft\elements\Entry::class,
'criteria' => [
'section' => 'events',
],
'fields' => ['heroImage'],
'transforms' => ['eventHeroImage']
],
[
'elementType' => \craft\elements\Entry::class,
'criteria' => [
'section' => ['news', 'articles', 'products'],
],
'fields' => ['heroImage', 'mainImage', 'articleBlocks:images.images'],
'transforms' => ['defaultHeroImage']
],
],
];
TIP
Notice that you can target fields inside Matrix or SuperTable fields with the syntax
<matrixFieldHandle>:<matrixTypeHandle>.<fieldHandle>
.
<matrixTypeHandle>
can be set to *
, which matches all matrix types. For SuperTable
fields, this is the only valid value, as SuperTable doesn't have different block types.
Finally, since you're using SEOMate (opens new window) to set up a waterfall of fields to use for your seo meta image tags, it makes more sense to generate these transforms based on the fields used:
<?php
return [
'volumes' => [
'employeeImages' => ['employeeThumbnail', 'employeePoster'],
'images' => ['listImage'],
],
'elements' => [
[
'elementType' => \craft\elements\Entry::class,
'criteria' => [
'section' => 'events',
],
'fields' => ['heroImage'],
'transforms' => ['eventHeroImage']
],
[
'elementType' => \craft\elements\Entry::class,
'criteria' => [
'section' => ['news', 'articles', 'products'],
],
'fields' => ['heroImage', 'mainImage', 'articleBlocks:images.images'],
'transforms' => ['defaultHeroImage']
],
],
'fields' => [
'seoImage' => ['seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
'mainImage' => ['seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
'heroImage' => ['seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
'listImage' => ['seoGenericImage', 'seoFacebookImage', 'seoTwitterImage'],
]
];
TIP
The field handles in fields
will target all elements, meaning also for matrix blocks
(which are just another element in Craft). So if you have a field called
image
that is attached to an entry type, and a field called image
inside
a matrix block, both will match the key image
in the example above.
That leaves us with a much more optimized set of transforms resulting in less transforms being generated overall, saving CPU cycles when new assets are uploaded, and a fair amount of disk space.
# Support for quick syntax
As of Imager 4.3.0, there's a new quick syntax, which also can be used in your config just as you would use named transforms:
<?php
return [
'volumes' => [
'employeeImages' => [
[400, 1200, 3/4],
[1200, 2000, 16/9]
],
]
];
# Console commands for generating transforms
Imager X comes with a powerful console command imager-x/generate
for batch
generation of transforms. You can create transforms based on volumes and
folders, or fields (as described above).
TIP
If the command doesn't show up when you type ./craft
in your project root,
or the command doesn't work at all, make sure the plugin is installed, that the
PHP version you're running on the command line has access to the database, and
that the necessary environment variables are set. Try using one of the built
in commands that comes with Craft, for instance ./craft backup/db
, if you're
unsure if console commands are working in general.
The available parameters for the command are:
# --volume (shorthand: -v)
Handle for volume to generate transforms for.
# --folderId (shorthand: -fid)
Id for folder inside a volume to generate transforms for.
# --recursive (shorthand: -r)
Toggles recursive mode on/off when transforming inside a volume.
# --field (shorthand: -f)
Handle of field to generate transforms for.
# --transforms (shorthand: -t)
Named transforms to generate. This can be a comma-separated list, or a single value.
If no transforms are passed to the command, Imager will look at the generate configuration to figure out which transforms to run. If transforms are passed, the configuration is ignored.
# --limit (shorthand: -l)
Number of assets that should be processed.
# --offset (shorthand: -o)
Offset used when selecting assets to process.
# --queue (shorthand: -q)
When set the console command will not create transforms when running, but instead create queue jobs. When processing many assets, this could be a more reliable way of making sure all the transforms are run (as long as you have a reliable queue runner set up).
# Examples
In the examples below, I use the shorthand syntax after showing the full syntax in the previous example.
# Create all transforms (based on config) for images in the root of volume `images`.
./craft imager-x/generate --volume=images
# Create all transforms for images in volume `images` - recursively.
./craft imager-x/generate -v=images --recursive
# Create all transforms for images in volume `images` - recursively, limited to 20 assets, starting with asset 40.
./craft imager-x/generate -v=images --recursive --limit=20 --offset=40
# Create all transforms for images in volume `images` - recursively, but create queue jobs instead.
./craft imager-x/generate -v=images --recursive --queue
# Create transforms `sweetTransform` and `hotTransform`,
# for all images in volume `images`
./craft imager-x/generate -v=images -r --transform=sweetTransform,hotTransform
# Create all transforms (based on config), for all images in folder with id `59`
# in volume `images`. Note, the folder must be in this volume, or nothing will happen.
./craft imager-x/generate -v=images --folderId=59
# Create all transforms (based on config) for all images *used* in fields
# with handle `myImage`.
./craft imager-x/generate --field=myImage
# Create transforms `sweetTransform` and `hotTransform` for all images *used* in
# fields with handle `myImage`.
./craft imager-x/generate -f=myImage -t=sweetTransform,hotTransform
TIP
Please note that cache settings will be respected also when running console commands. Meaning, if caching is enabled, Imager will only generate the transforms that are missing, or are expired.
# Element action for generating transforms
If you have configured any volumes in your generate config, a new element action will be available for assets, called "Generate transforms". By selecting assets and running this action, all configured transforms for the volume that the assets are in, will be generated.