Please wait...

General notes for differences between v1 and v2

We now require PHP >= 7.2.

1. Most of the code is now using typed params and return types.
Instead of:

public function abc($text, $intNum)

you’ll see:

public function abc(string $text, int $intNum): string

This means you have to edit any code that extends core functionality and make sure the method declarations are compatible.

2. All extension dependencies were moved in the app main composer.json file, no more specific composer.json for each extension which would generally cause issues and conflicts between the libraries.

3. We’re using composer now, so all libraries are versioned and stored in the vendor folder.
The old apps/common/vendors folder is only used for libraries that aren’t available via composer.

4. We have added a set of shortcut methods for easier access for the app components.
Here’s a small table:

Yii::app()-> becomes app()->
Yii::app()->assetManager-> becomes assetManager()->
Yii::app()->hooks-> becomes hooks()->
Yii::app()->urlManager-> becomes urlManager()->
Yii::app()->request-> becomes request()->
Yii::app()->notify-> becomes notify()->

You can look into apps/common/components/utils/functions.php to see all the shortcuts. We recommend using these shortcuts from now on as it makes things easier to read.

5. Instead of Yii::t() we advise using t().

6. Generally we used to access the app options via Yii::app()->options->get('category.key') even for option categories that had model classes, for example, to get the site name, we would do Yii::app()->options->get('system.common.site_name').
We added getters for most of the option models properties, so we advise using things like (new OptionCommon())->getSiteName() instead.
If the option isn’t part of a model, you can access it with options()->get('category.key').

7. Application params used to be accessed via Yii::app()->params['some.param']. We advise using the app_param('some.param', 'defaultValueOptional') instead.
There’s also app_param_set($key, $value) to set a param and also app_param_unset($key) to unset a param.

8. Since we’re using types params for methods/functions, if a method signature accepts strings, make sure you pass strings to it, if it accepts ints, pass it ints, and so on. Use type casting if needed, i.e: $this->abc((string)$text, (int)$num)

9. CSV parsing will only be done using league/csv, see

10. Generators will be used as much as possible when loading data in batches from database, namely methods like getModels() which used to be called in a while loop.

11. We added model collections, see apps/common/models/collection which return an instance of \Illuminate\Support\Collection, see Which can be used like:

CampaignCollection::findAll($criteria)->mapWithKeys(function(Campaign $model) {
return [$campaign->campaign_id => $campaign->name];

This is the desired way to manipulate arrays.

12. Database charset has been changed to `utf8mb4`.

13. Handling scripts from controllers will be done via:

Controller::getPageScripts, Controller::addPageScript, Controller::addPageScripts

14. Handling styles from controllers will be done via:

Controller::getPageStyles, Controller::addPageStyle, Controller::addPageStyles

15. Unit tests were added for most of the code base.

16. Acceptance tests were added for most used routes.

17. Use html_encode($text) when echoing content.

18. Use short array syntax [1, 2, 3] instead of long one array(1, 2, 3).

19. The `extensionMimes` component, which is an instance of `FileExtensionMimes` now uses `ralouphie/mimey` to load much more mimes by default, then we add our mimes over those. The calls to the component remain unchanged:

app()->extensionMimes->get(['png', 'jpg', 'jpeg', 'gif'])->toArray()

20. Removed all calls to ini_set('max_execution_time', '...') and set_time_limit() and ignore_user_abort()

21. Removed PHPMailer from the app.

22. Remove any attempts related to setting the memory limit of the app.

23. Customer suppression list import/export has been improved and it’s about ~300% faster.

24. Email Blacklist import/export has been improved and it’s about ~300% faster.

25. Removed


26. All remote http calls are now made via `GuzzleHttp\Client`

27. AllListsSubscribersFilters now uses generators and collections to complete the actions

28. Added a DI container, mainly to use it with option model. Use container()->get(OptionModel::class) instead of new OptionModel(). All option models are auto-wired.

29. All calls to options()->get('system.exporter.*') have been replaced with OptionExporter::methodName.

30. All calls to options()->get('system.importer.*') have been replaced with OptionImporter::methodName.

31. Removed all error suppression calls (i.e: no more @mkdir() but mkdir())

32. All classes for survey field types (stored in apps/customer/components/survey-field-builder) received the Survey prefix, so it’s `SurveyFieldBuilderType` instead of `FieldBuilderType` and so on. The classes path changed as well in the `survey_field_type` table, so now instead of
we have
Also, the entire component has been significantly rewritten.

33. All classes for list field types (used to be stored in apps/customer/components/field-builder, now they are in apps/customer/components/list-field-builder) received the List prefix, so it’s `ListFieldBuilderType` instead of `FieldBuilderType` and so on. The classes path changed as well in the `list_field_type` table, so now instead of
we have
Also, the entire component has been significantly rewritten.

34. The class `AllListsSubscribersFilters` for backend area, stored in `apps/common/models` has now been renamed into `AllCustomersListsSubscribersFilters`.

35. Extension translation files will now use `ext` as suffix not as prefix.

36. There is a new extensions guideline, see this article

37. Removed the Invoicr class in favour of Dompdf. If you were changing the invoices programmatically, please revise your process.

38. Inside view files, we’re not using $this anymore, but $controller

39. Double check the hook names you connect to, some of them changed their naming.
For example, instead of customer_controller_ext_ckeditor_before_action we
now have customer_controller_ckeditor_ext_ckeditor_before_action.
This happens because we need to avoid any ambiguity.