PHPackages                             basilicom/pimcore-plugin-migration-toolkit - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. basilicom/pimcore-plugin-migration-toolkit

ActivePimcore-bundle[Utility &amp; Helpers](/categories/utility)

basilicom/pimcore-plugin-migration-toolkit
==========================================

Set of Migration Helpers and further Migration Tools for Pimcore Migrations.

v6.0.3(5mo ago)410.0k↓43.9%GPL-3.0-or-laterPHPPHP &gt;=8.3CI failing

Since Jun 2Pushed 5mo ago4 watchersCompare

[ Source](https://github.com/basilicom/pimcore-plugin-migration-toolkit)[ Packagist](https://packagist.org/packages/basilicom/pimcore-plugin-migration-toolkit)[ RSS](/packages/basilicom-pimcore-plugin-migration-toolkit/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (4)Dependencies (1)Versions (59)Used By (0)

Pimcore Plugin Migration Toolkit
================================

[](#pimcore-plugin-migration-toolkit)

License: GPL v3

Version information
-------------------

[](#version-information)

Bundle VersionPHPPimcore^4.0^7.4^6.8^4.0^8.0^10.0^5.0^8.1^11.0^6.0^8.3^12.0Why?
----

[](#why)

In every project we have migrations for the same things. Like Thumbnails, Classes, etc.

This plugin provides you with the migration helpers and further tools.

Installation
------------

[](#installation)

```
composer require basilicom/pimcore-plugin-migration-toolkit

```

### Activate Plugin

[](#activate-plugin)

- Add to config/bundles.php

```
return [
    ...
    PimcorePluginMigrationToolkitBundle::class => ['all' => true],
];

```

Usage Migration Helpers
-----------------------

[](#usage-migration-helpers)

For all migrations extend them from the class `AbstractAdvancedPimcoreMigration`.

### Migration Data

[](#migration-data)

If a migration needs data it needs to be located in the following folder: `/Migrations/data/`

### System Settings

[](#system-settings)

System Settings can be set via config.yaml.

Example:

```
pimcore_admin:
    branding:
        login_screen_invert_colors: true
        color_login_screen: '#001b36'
        color_admin_interface: '#001b36'
        login_screen_custom_image: '/build/images/backend/background-login-screen.jpg'
```

### Language Settings

[](#language-settings)

Language Settings are part of the System Settings and can be set via config.yaml.

Example:

```
pimcore:
    general:
        timezone: Europe/Berlin
        redirect_to_maindomain: false
        language: en
        valid_languages: 'de,de_CH,en,fr_CH'
        fallback_languages:
          de: ''
          de_CH: ''
          en: ''
          fr_CH: ''
        default_language: en
        debug_admin_translations: false
```

### Website Settings

[](#website-settings)

Example: Up

```
$websiteSettingsMigrationHelper = $this->getWebsiteSettingsMigrationHelper();
$websiteSettingsMigrationHelper->createOfTypeText('text', 'text hier');
$websiteSettingsMigrationHelper->createOfTypeDocument('document', 1);
$websiteSettingsMigrationHelper->createOfTypeAsset('asset', 1);
$websiteSettingsMigrationHelper->createOfTypeObject('object', 1);
$websiteSettingsMigrationHelper->createOfTypeBool('bool', false);
```

Example: Down

```
$websiteSettingsMigrationHelper = $this->getWebsiteSettingsMigrationHelper();
$websiteSettingsMigrationHelper->delete('text');
$websiteSettingsMigrationHelper->delete('document');
$websiteSettingsMigrationHelper->delete('asset');
$websiteSettingsMigrationHelper->delete('object');
$websiteSettingsMigrationHelper->delete('bool');
```

### Static Routes

[](#static-routes)

Example: Up

```
$staticRoutesMigrationHelper = $this->getStaticRoutesMigrationHelper();
$staticRoutesMigrationHelper->create(
    'route',
    '/pattern',
    '/reverse',
    'controller',
    'variable1,variable2',
    'default1,default2',
    10
);
$staticRoutesMigrationHelper->create(
    'route1',
    '/pattern1',
    '/reverse1',
    'controller1'
);
```

Example: Down

```
$staticRoutesMigrationHelper = $this->getStaticRoutesMigrationHelper();
$staticRoutesMigrationHelper->delete('route');
$staticRoutesMigrationHelper->delete('route1');
```

### User Roles

[](#user-roles)

There is no way to remove the workspaces (dataobjects, documents or assets).

Even when deleting a user role in the pimcore backend the workspace data stays in the database.

Example: Up

```
$roleName = 'migrationRole';
$path = '/';

$userRolesMigrationHelper = $this->getUserRolesMigrationHelper();
$userRolesMigrationHelper->create(
    $roleName,
    ['dashboards', 'admin_translations'],
    ['doctype'],
    ['class'],
    ['de', 'en'],
    ['de']
);

$userRolesMigrationHelper->addWorkspaceDataObject($roleName, $path, true, true, false, true, false, false, false, false, false, false, false, 'layout1,layout2', 'de,en', 'de,en');
$userRolesMigrationHelper->addWorkspaceDocument($roleName, $path, true, true, false, true, false, true, false, false, false, false, false);
$userRolesMigrationHelper->addWorkspaceAsset($roleName, $path, true, true, true, false, false, false, false, false, false);

// PHP 8 - Named Arguments with the same setting as above
$userRolesMigrationHelper->addWorkspaceDataObject($roleName, $path, list: true, view: true, publish: true, layouts: 'product_productproductpolo', lEdit: 'en,de,de_CH,fr_CH', lView: 'en,de,de_CH,fr_CH');
$userRolesMigrationHelper->addWorkspaceDocument($roleName, $path, list: true, view: true, publish: true);
$userRolesMigrationHelper->addWorkspaceAsset($roleName, $path, list: true, view: true, publish: true);
```

Example: Down

```
$roleName = 'migrationRole';
$path = '/';
$userRolesMigrationHelper = $this->getUserRolesMigrationHelper();

$userRolesMigrationHelper->updateWorkspaceDataObject($roleName, $path, true, true, false, true, false, false, false, false, false, false, false, 'layout1,layout2', 'de,en', 'de,en');
$userRolesMigrationHelper->updateWorkspaceDocument($roleName, $path, true, true, false, true, false, false, false, false, false, false, false);
$userRolesMigrationHelper->updateWorkspaceAsset($roleName, $path, true, true, true, false, false, false, false, false, false);

// PHP 8 - Named Arguments with the same setting as above
$userRolesMigrationHelper->updateWorkspaceDataObject($roleName, $path, list: true, view: true, publish: true, layouts: 'product_productproductpolo', lEdit: 'en,de,de_CH,fr_CH', lView: 'en,de,de_CH,fr_CH');
$userRolesMigrationHelper->updateWorkspaceDocument($roleName, $path, list: true, view: true, publish: true);
$userRolesMigrationHelper->updateWorkspaceAsset($roleName, $path, list: true, view: true, publish: true);

$userRolesMigrationHelper->deleteWorkspaceDataObject($roleName, $path);
$userRolesMigrationHelper->deleteWorkspaceDocument($roleName, $path);
$userRolesMigrationHelper->deleteWorkspaceAsset($roleName, $path);

$userRolesMigrationHelper->delete($roleName);
```

### Bundle / Extension

[](#bundle--extension)

It is not possible to enable and install one bundle in one migration!

You need to make two migrations one with enable (disable) and one with install (uninstall) and then run it with the command [Migrate in separate process](#migrate-in-separate-process). Otherwise it would not find the newly enabled bundle for the installation.

Example: Up

```
$bundleMigrationHelper = $this->getBundleMigrationHelper();
$bundleMigrationHelper->enable('Basilicom\PimcorePluginMigrationToolkit\PimcorePluginMigrationToolkitBundle');
```

Example: Down

```
$bundleMigrationHelper = $this->getBundleMigrationHelper();
$bundleMigrationHelper->disable('Basilicom\PimcorePluginMigrationToolkit\PimcorePluginMigrationToolkitBundle');
```

### Class Definitions

[](#class-definitions)

Example: Up

```
$className = 'testing';
$classDefinitionMigrationHelper = $this->getClassDefinitionMigrationHelper();
$jsonPath = $classDefinitionMigrationHelper->getJsonDefinitionPathForUpMigration($className);
$classDefinitionMigrationHelper->createOrUpdate($className, $jsonPath);
```

Example: Down

```
$className = 'testing';
$classDefinitionMigrationHelper = $this->getClassDefinitionMigrationHelper();
$classDefinitionMigrationHelper->delete($className);
// OR
$jsonPath = $classDefinitionMigrationHelper->getJsonDefinitionPathForDownMigration($className);
$classDefinitionMigrationHelper->createOrUpdate($className, $jsonPath);
```

### Objectbricks

[](#objectbricks)

Example: Up

```
$objectbrickName = 'brick';
$objectbrickMigrationHelper = $this->getObjectbrickMigrationHelper();
$jsonPath = $objectbrickMigrationHelper->getJsonDefinitionPathForUpMigration($className);
$objectbrickMigrationHelper->createOrUpdate($objectbrickName, $jsonPath);
```

Example: Down

```
$objectbrickName = 'brick';
$objectbrickMigrationHelper = $this->getObjectbrickMigrationHelper();
$objectbrickMigrationHelper->delete($objectbrickName);
// OR
$jsonPath = $objectbrickMigrationHelper->getJsonDefinitionPathForDownMigration($className);
$objectbrickMigrationHelper->createOrUpdate($objectbrickName, $jsonPath);
```

### Fieldcollection

[](#fieldcollection)

Example: Up

```
$key = 'test';
$fieldcollectionMigrationHelper = $this->getFieldcollectionMigrationHelper();
$jsonPath = $fieldcollectionMigrationHelper->getJsonDefinitionPathForUpMigration($className);
$fieldcollectionMigrationHelper->createOrUpdate($key, $jsonPath);
```

Example: Down

```
$key = 'test';
$fieldcollectionMigrationHelper = $this->getFieldcollectionMigrationHelper();
$fieldcollectionMigrationHelper->delete($key);
// OR
$jsonPath = $fieldcollectionMigrationHelper->getJsonDefinitionPathForDownMigration($className);
$fieldcollectionMigrationHelper->createOrUpdate($key, $jsonPath);
```

### Classification Store

[](#classification-store)

Classification Stores cannot be created with given ID.

But the ID is needed for the store field in a class.

Therefore using the name is needed.

But the name is not unique, so always use a unique name.

So be aware of that.

Example: Up

```
$groupName = 'GroupName';
$fieldName = 'FieldName';
$title = 'Title fo FieldName';

$classificationStoreMigrationHelper = $this->getClassificationStoreMigrationHelper();
$storeConfig = $classificationStoreMigrationHelper->createOrUpdateStore(
    'StoreName',
    'Description'
);

// typehint says it should return int, but it is string
$storeId = (int) $storeConfig->getId();

$classificationStoreMigrationHelper->createOrUpdateGroup(
    $groupName,
    'Description',
    $storeId
);

// Input
$definition = new ClassDefinitionData\Input();
$definition->setWidth(500);
$definition->setName($fieldName);
$definition->setTitle($title);

$classificationStoreMigrationHelper->createOrUpdateKey(
    $fieldName,
    $title,
    'Description',
    $definition,
    $storeId,
    $groupName
);
```

Example: Down

```
$storeName = 'StoreName';
$classificationStoreMigrationHelper = $this->getClassificationStoreMigrationHelper();
$storeConfig = $classificationStoreMigrationHelper->getStoreByName($storeName);
// typehint says it should return int, but it is string
$storeId = (int) $storeConfig->getId();
$classificationStoreMigrationHelper->deleteGroup($groupName, $storeId);
$classificationStoreMigrationHelper->deleteKey($fieldName, $storeId);
$classificationStoreMigrationHelper->deleteStore($storeName);
```

FieldDefinition Examples
------------------------

[](#fielddefinition-examples)

```
// Textarea
$definition = new ClassDefinitionData\Textarea();
$definition->setWidth(500);
$definition->setHeight(100);
$definition->setShowCharCount(true);
$definition->setName($fieldName);
$definition->setTitle($title);

// Select
$definition = new ClassDefinitionData\Select();
$definition->setWidth(500);
$definition->setDefaultValue('');
$definition->setOptions([]);
$definition->setName($fieldName);
$definition->setTitle($title);
```

### Custom Layouts

[](#custom-layouts)

Custom Layouts will get the id like "lower()".

```
const CUSTOM_LAYOUT = [
    'classId' => 'reference',
    'name' => 'readOnly'
];
```

Example: Up

```
$customLayoutMigrationHelper = $this->getCustomLayoutMigrationHelper();
$jsonPath = $customLayoutMigrationHelper->getJsonDefinitionPathForUpMigration(self::CUSTOM_LAYOUT['name'], self::CUSTOM_LAYOUT['classId']);
$customLayoutMigrationHelper->createOrUpdate(
    self::CUSTOM_LAYOUT['name'],
    self::CUSTOM_LAYOUT['classId'],
    $jsonPath
);
```

Example: Down

```
$customLayoutMigrationHelper = $this->getCustomLayoutMigrationHelper();
$customLayoutMigrationHelper->delete(
    self::CUSTOM_LAYOUT['name'],
    self::CUSTOM_LAYOUT['classId']
);
// OR
$jsonPath = $customLayoutMigrationHelper->getJsonDefinitionPathForDownMigration(self::CUSTOM_LAYOUT['name'], self::CUSTOM_LAYOUT['classId']);
$customLayoutMigrationHelper->createOrUpdate(
    self::CUSTOM_LAYOUT['name'],
    self::CUSTOM_LAYOUT['classId'],
    $jsonPath
);
```

### Document (Page)

[](#document-page)

```
const PAGE = [
    'key' => 'diga',
    'name' => 'DiGA',
    'controller' => 'Search',
    'parentPath' => '/',
];
```

Example: Up

```
$documentMigrationHelper = $this->getDocumentMigrationHelper();
$documentMigrationHelper->createPageByParentPath(
    self::PAGE['key'],
    self::PAGE['name'],
    self::PAGE['controller'],
    self::PAGE['parentPath']
);
```

Example: Down

```
$documentMigrationHelper = $this->getDocumentMigrationHelper();
$documentMigrationHelper->deleteByPath(
    self::PAGE['parentPath'].self::PAGE['key']
);
```

### Object (Folder)

[](#object-folder)

Example: Up

```
$dataObjectMigrationHelper = $this->getDataObjectMigrationHelper();
$dataObjectMigrationHelper->createFolderByParentId('folder1', 1);
$dataObjectMigrationHelper->createFolderByPath('/folder2/subfolder');
```

Example: Down

```
$dataObjectMigrationHelper = $this->getDataObjectMigrationHelper();
$dataObjectMigrationHelper->deleteById(2);
$dataObjectMigrationHelper->deleteByPath('/folder2');
```

### Asset (File)

[](#asset-file)

Example: Up

```
$assetMigrationHelper = $this->getAssetMigrationHelper();
$newAsset = $assetMigrationHelper->createAsset('./project/folder/asset.png', '/pimcore/asset/folder', 'myAsset.png');
$assetMigrationHelper->updateAsset($newAsset, './project/folder/updatedAsset.png', 'updatedAsset.png');

```

Example: Down

```
$assetMigrationHelper = $this->getAssetMigrationHelper();
$assetMigrationHelper->deleteById(2);
$assetMigrationHelper->deleteByPath('/pimcore/asset/folder/myAsset.png');

```

### Asset (Folder)

[](#asset-folder)

Example: Up

```
$assetMigrationHelper = $this->getAssetMigrationHelper();
$assetMigrationHelper->createFolderByParentId('name', 1);
$assetMigrationHelper->createFolderByPath('/asset1/subasset');
```

Example: Down

```
$assetMigrationHelper = $this->getAssetMigrationHelper();
$assetMigrationHelper->deleteById(2);
$assetMigrationHelper->deleteByPath('/asset1');
```

### QuantityValue Unit

[](#quantityvalue-unit)

Example: Up

```
$quantityValueUnitMigrationHelper = $this->getQuantityValueUnitMigrationHelper();
$quantityValueUnitMigrationHelper->createOrUpdate('uniqueid', 'abr', 'Long Abbreviation');
```

Example: Down

```
$quantityValueUnitMigrationHelper = $this->getQuantityValueUnitMigrationHelper();
$quantityValueUnitMigrationHelper->delete('uniqueid');
```

### MySQL Helper

[](#mysql-helper)

#### Example: Up

[](#example-up)

to load and execute a large sql file, do the following:

```
$mysqlHelper = $this->getMySqlMigrationHelper();
$sqlFile = $mysqlHelper->loadSqlFile('your_sql_file.sql');
$this->addSql($sqlFile);
```

all sql files should be stored in the `sql` subdirectory within the migration's data directory:

```
project/src/Migrations/data//sql
```

#### Example: Down

[](#example-down)

```
$mysqlHelper = $this->getMySqlMigrationHelper();
$sqlFile = $mysqlHelper->loadSqlFile('your_sql_file.sql', $mysqlHelper::DOWN);
$this->addSql($sqlFile);
```

please keep in mind the changed path in case of down migrations:

```
project/src/Migrations/data//sql/down
```

### Translation Helper

[](#translation-helper)

to add the translations into the pimcore shared/admin translations. default domain is 'messages' (shared translations). but you can change it to any domain, also 'admin' (admin translations).

```
protected array $translations = [
    'translation.key' => [
        'en' => 'Test en',
        'de' => 'Test de',
    ],
];
```

#### Example: Up

[](#example-up-1)

```
$this->getTranslationMigrationHelper()->addTranslations($this->translations);
```

#### Example: Down

[](#example-down-1)

```
$this->getTranslationMigrationHelper()->removeTranslationsByKey(array_keys($this->translations));
```

Commands
--------

[](#commands)

### Migrate in separate process

[](#migrate-in-separate-process)

Executes the same migrations as the `doctrine:migrations:migrate` command, but each one is run in a separate process, to prevent problems with PHP classes that changed during the runtime.

```
bin/console basilicom:migrations:migrate-in-separate-processes
```

You're also able to migrate only specific bundles using the bundle prefix.

```
bin/console basilicom:migrations:migrate-in-separate-processes --bundle "App"
bin/console basilicom:migrations:migrate-in-separate-processes --bundle "Pimcore"

bin/console basilicom:migrations:migrate-in-separate-processes -b "App"
bin/console basilicom:migrations:migrate-in-separate-processes -b "Pimcore"
```

In some cases you might run migrations on large datasets. Therefor 120s of timeout per migration won't be enough. To adapt the timeout just pass the `--timeout` option. To unset the timeout at all, pass `0`.

```
bin/console basilicom:migrations:migrate-in-separate-processes --timeout 0
bin/console basilicom:migrations:migrate-in-separate-processes --timeout 180
```

```
bin/console basilicom:migrations:migrate-in-separate-processes -t 0
bin/console basilicom:migrations:migrate-in-separate-processes -t 180
```

### Import Translations

[](#import-translations)

To import a csv file, like the exported shared translations from pimcore. To Pimcore shared translations. Or to Pimcore admin translations.

```
# examples
bin/console basilicom:import:translations /path/to/project/translations/shared-translations.csv
bin/console basilicom:import:translations /path/to/project/translations/shared-translations.csv --replaceExistingTranslation
bin/console basilicom:import:translations /path/to/project/translations/admin-translations.csv --replaceExistingTranslation --admin
```

Ideas
-----

[](#ideas)

- command: `basilicom:migrations:generate `
    - types e.g:
        - general migration for extended class only
        - class migration template with folders
        - ...
- enhance command: `basilicom:migrations:migrate-in-separate-processes`
    - to also revert `prev` or ``

###  Health Score

54

—

FairBetter than 97% of packages

Maintenance72

Regular maintenance activity

Popularity30

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity84

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 65% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~36 days

Recently: every ~176 days

Total

56

Last Release

160d ago

Major Versions

v3.2.0 → v4.10.02022-08-17

v4.10.3 → v5.0.02023-05-17

v2.0.2 → v4.10.42023-11-14

v4.10.4 → v5.0.32023-11-14

v5.0.5 → v6.0.02025-11-10

PHP version history (3 changes)v1.2.1PHP &gt;=7.3

v4.3.0PHP ^8.0

v6.0.0PHP &gt;=8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/afb6145ee5c0c6af7662a537e76ee9c679d30e7e6217636d72576ea5ccd8b002?d=identicon)[AlexanderHeidrich](/maintainers/AlexanderHeidrich)

---

Top Contributors

[![kerstinbasilicom](https://avatars.githubusercontent.com/u/38213550?v=4)](https://github.com/kerstinbasilicom "kerstinbasilicom (117 commits)")[![AlexanderHeidrich](https://avatars.githubusercontent.com/u/9350895?v=4)](https://github.com/AlexanderHeidrich "AlexanderHeidrich (53 commits)")[![clemenskapelle](https://avatars.githubusercontent.com/u/98171870?v=4)](https://github.com/clemenskapelle "clemenskapelle (6 commits)")[![fabfischer](https://avatars.githubusercontent.com/u/1053032?v=4)](https://github.com/fabfischer "fabfischer (3 commits)")[![bas-denisdi](https://avatars.githubusercontent.com/u/90613758?v=4)](https://github.com/bas-denisdi "bas-denisdi (1 commits)")

### Embed Badge

![Health badge](/badges/basilicom-pimcore-plugin-migration-toolkit/health.svg)

```
[![Health](https://phpackages.com/badges/basilicom-pimcore-plugin-migration-toolkit/health.svg)](https://phpackages.com/packages/basilicom-pimcore-plugin-migration-toolkit)
```

###  Alternatives

[dachcom-digital/formbuilder

Pimcore FormBuilder - create forms easily!

96269.7k](/packages/dachcom-digital-formbuilder)[elements/process-manager-bundle

The Process Manager allows you to manage (define,execute...) arbitrary processes/commands in the Pimcore backend.

49633.0k5](/packages/elements-process-manager-bundle)[pimcore/data-importer

Adds a comprehensive import functionality to Pimcore Datahub

44763.4k2](/packages/pimcore-data-importer)[pimcore/output-data-config-toolkit-bundle

21256.8k3](/packages/pimcore-output-data-config-toolkit-bundle)[instride/data-definitions

Data Definitions allows you to define your DataObject Imports and Exports using a nice GUI and re-run the definitions as often you like.

8117.7k](/packages/instride-data-definitions)[pimcore/object-merger

13550.4k1](/packages/pimcore-object-merger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
