Updating Plugins for Craft 3.4

Craft 3.4 introduced a few changes in behavior for plugins and modules.

Control Panel Styles #

Craft’s control panel got a new look and feel in Craft 3.4. If your plugin is providing its own styling, or doing anything with JavaScript off the beaten path, make sure that it continues to function and look right.

Use the craftcms-sass npm package to pull in several Sass macros and properties that will help your plugin match the control panel styling.

Saving Associative Arrays to Project Config #

Craft 3.4 now recursively sorts all associative arrays by their keys when they are saved to the Project Config.

For example, if you were to save an array with keys foo, bar to the project config, it would get reordered to bar, foo.

If you are storing an associative array where the order is important (such as editable table data), you can pass it through packAssociativeArray() before setting it on the Project Config. That helper function will restructure the array in a way that is non-associative, without loosing a record of its original keys.

$myArray = ['foo' => 1, 'bar' => 2];

// "Pack" the array so it doesn't get reordered to [bar=>2,foo=>1]
$packedArray = \craft\helpers\ProjectConfig::packAssociativeArray($myArray);

Craft::$app->projectConfig->set($configKey, $packedArray);

If you do this, make sure you restore the array to its original form when retrieving its value from the Project Config, using unpackAssociativeArray().

$packedArray = Craft::$app->projectConfig->get($configKey);

$myArray = \craft\helpers\ProjectConfig::unpackAssociativeArray($packedArray);

Custom Queue Drivers #

Craft 3.4 includes yii2-queue 2.3, which introduced some minor breaking changes for custom queue drivers. In addition, if you have a queue driver that implements craft\queue\QueueInterface, that has been updated to require new getTotalJobs(), getJobDetails(), retryAll() and releaseAll() methods.

Setting Custom Field Values #

Before Craft 3.4, it was technically possible to set field values directly on elements under certain conditions, however that approach was never documented or supported, because it would only work for field values that hadn’t been retrieved in any way yet. As of Craft 3.4, it’s no longer possible under any circumstances. So make sure your plugin or module is always setting field values using setFieldValue() or setFieldValues().

// Bad
$entry->myTextField = 'Hello';

// Good
$entry->setFieldValue('myTextField', 'Hello');

Setting Active Record Values #

Before Craft 3.4, it was possible to set an array value on an Active Record object, and then continue accessing it as an array right up until save() was called on it, at which point it would become JSON-encoded. As of Craft 3.4, array values get JSON-encoded immediately, so that’s no longer practical.

// Craft 3.3 and earlier:
$record->columnName = ['foo' => 'bar'];
echo $record->columnName; // --> ['foo' => 'bar'] (array)
$record->save();
echo $record->columnName; // --> '{"foo":"bar"}' (JSON)

// Craft 3.4 and later:
$record->columnName = ['foo' => 'bar'];
echo $record->columnName; // --> '{"foo":"bar"}' (JSON)