Version: Edit on GitHub

Upgrading Pimcore from Version 5 to Version 6.0

Important things to check and consider prior the update

  • PHP >=7.2 is required
  • IE11 is not officially supported anymore. That doesn't mean that IE11 won't work anymore straight away (although a warning will be shown on login), but that's not guaranteed anymore for the entire lifecycle of v6.
  • Symfony 4 is the default version used by Pimcore 6, if you'd like to stay on the current LTS version of Symfony (3.4), please add the following to your project-specific composer.json: "symfony/symfony": "^3.4.17"

Preparatory Work

IMPORTANT CHANGES PRIOR THE UPDATE!

Adapt your composer.json BEFORE the update!

Due to the removal of sensio/distribution-bundle it's necessary to update your projects composer.json.

To do so, just replace the following lines in your existing composer.json file:

    "post-install-cmd": [
      "Pimcore\\Composer::postInstall",
      "@symfony-scripts"
    ],
    "post-update-cmd": [
      "Pimcore\\Composer::postUpdate",
      "@symfony-scripts",
      "Pimcore\\Composer::executeMigrationsUp"
    ],
    "pre-package-update": [
      "Pimcore\\Composer::prePackageUpdate"
    ],
    "symfony-scripts": [
      "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
      "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
      "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
      "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
    ]     

with the following configuration:

    "post-install-cmd": [
      "Pimcore\\Composer::postInstall",
      "@pimcore-scripts"
    ],
    "post-update-cmd": [
      "Pimcore\\Composer::postUpdate",
      "@pimcore-scripts",
      "Pimcore\\Composer::executeMigrationsUp",
      "@pimcore-scripts"
    ],
    "pimcore-scripts": [
      "Pimcore\\Composer::clearCache",
      "Pimcore\\Composer::installAssets"
    ]

Add database config file /app/config/local/database.yml BEFORE the update!

Database settings were moved to doctrine bundle's default configuration structure (Symfony config-tree), so it is important to create a database.yml with your DB connection values manually before running the update, see also #3268

doctrine:
    dbal:
        connections:
            default:
                user: username
                password: password
                dbname: dbname
                host: host
                port: 3306

Alternatively you can add the database configuration directly to your project's config.yml or any other loaded config file.

Update your web/app.php

Update your web/app.php to the latest available version here: https://raw.githubusercontent.com/pimcore/skeleton/master/web/app.php

Update your Config

If your're using pimcore_admin.dataObjects in your config, please rename dataObjects to objects.

Run the content migration script

wget https://gist.githubusercontent.com/brusch/56f0405b5210e97bf9db6c48cd237bf3/raw/0a946a8e159862fae1d80edbb40388ce3b30fa75/pimcore-6-migrate-content.php
php pimcore-6-migrate-content.php
rm pimcore-6-migrate-content.php

Script should run through without any output.

Overview of Changes

General Changes

  • Removed support for Zend_Paginator_Adapter_Interface and Zend_Paginator_AdapterAggregate on listing classes use the Zend Framework 2/3 classes instead
  • Removed support for Zend_Date, use Carbon\Carbon instead
  • sensio/generator-bundle has been removed in favour of Symfony 4. You can still use pimcore:generate:bundle command to generate Pimcore Bundle Skeleton.
  • twig/twig dependency was changed from ^2.0 to ^2.4
  • sensio/distribution-bundle has been removed.
  • Image Thumbnails: removed the option svgPlaceholder, use lowQualityPlaceholder instead.
  • Maintenance Job: Removed event pimcore.system.maintenance and the old way using Job to add custom tasks. Please instead register the maintenance task as a service
  • Pimcore 4 Compatibility Bridge / Legacy Mode is not supported anymore
  • Methods getChilds(), setChilds(), hasChilds() and hasNoChilds() are removed from all ElementInterface classes, use the *Children() equivalents instead
  • Google Analytics tracking using Pimcore\Google\Analytics is not possible anymore
  • bundles/pimcorecore/js/targeting.js is now loaded asynchronously - if you have depending custom code you probably have to adapt it
  • For all Listing classes it's not necessary anymore to call the load() method before calling the actual getter for the items
  • The data properties of all Listing classes are now protected instead of public
  • Commands need to be registered as services and tagged with the console.command tag.
  • System Settings are now stored as Symfony Config, located in var/config/system.yml - if you are using environment specific config files such as system_stage.php you have to migrate them manually.
  • Removed internal feature toggle system: Pimcore\FeatureToggles\*

Data Object Changes

  • Checkbox data-type is tri-state from now on (null, true, false). A default value can be set for the editmode (not on database-level). Null means that inheritance is enabled, otherwise it isn't. Until now, inheritance was enabled also for false value. In case you do want to have the same behavior as before the update you will need to change all current 0 values to null before updating. After the update you need to change the default value in the Classdefinition file from false to null.
  • Removed the Persona and Persona Multiselect data object data-types, please use TargetGroup and TargetGroupMultiselect instead
  • Pimcore\Model\DataObject\Concrete::getValueFromParent() and Pimcore\Model\DataObject\Objectbrick\Data\AbstractData::getValueFromParent throws an InheritanceParentNotFoundException if it can't get a value from a parent
  • Getter hook preGetValue() requires now the use of Pimcore\Model\DataObject\PreGetValueHookInterface, all your classes using preGetValue() need to implement this interface.
  • Namespace Pimcore\Model\Object is not supported anymore, use Pimcore\Model\DataObject instead
  • Custom object data-types must implement interfaces (CustomResourcePersistingInterface, QueryResourcePersistenceAwareInterface and ResourcePersistenceAwareInterface)

Removed Classes, Interfaces, Methods, Constants, Functions, Aliases

is_includeable()
Pimcore\FeatureToggles\*
Pimcore\Google\Analytics
Pimcore\Http\Context\PimcoreContextResolverAwareInterface
Pimcore\Bundle\CoreBundle\EventListener\Frontend\AbstractFrontendListener
Pimcore\Bundle\CoreBundle\EventListener\AbstractContextAwareListener
Pimcore\Model\DataObject\ClassDefinition\Data\Persona
Pimcore\Model\DataObject\ClassDefinition\Data\Personamultiselect
Pimcore\Model\Tool\Targeting\Persona
Pimcore\Model\Tool\Targeting\Persona\Listing
Pimcore\Cache::addClearedTag()
Pimcore\Model\Document\Page\Dao::hasPersonaSpecificElements()
Pimcore\Model\Document\Page::getKeywords()
Pimcore\Model\Document\Page::setKeywords()
Pimcore\Model\Document\Page::setPersonas()
Pimcore\Model\Document\Page::getPersonas()
Pimcore\Model\Document\Page::getPersonaElementPrefix()
Pimcore\Model\Document\Page::getPersonaElementName()
Pimcore\Model\Document\Page::setUsePersona()
Pimcore\Model\Document\Page::getUsePersona()
Pimcore\Model\Document\Page::PERSONA_ELEMENT_PREFIX_PREFIXPART
Pimcore\Model\Document\Page::PERSONA_ELEMENT_PREFIX_SUFFIXPART
Pimcore\Config::DEFAULT_ENVIRONMENT
Pimcore\Document\Newsletter\AddressSourceAdapter\DefaultAdapter::addPersonaConditions()
Pimcore\Version::getBuildDate()
Pimcore\Tool::isFrontentRequestByAdmin()
Pimcore\Model\Version::cleanHistory()
Pimcore\Model\Version\Dao::getOutdatedVersionsSteps()
Pimcore\Model\Version\Dao::getOutdatedVersionsDays()
Pimcore\Model\Version\Dao::disableSlowQueryLog()
Pimcore\Model\Version\Dao::enableSlowQueryLog()
Pimcore\Model\DataObject::preGetValue()
Pimcore\Model\DataObject\ClassDefinition::addNewDataField()
Pimcore\Model\DataObject\ClassDefinition::removeExistingDataField()
Pimcore\Model\Translation\AbstractTranslation::getDate()
Pimcore\Event\SystemEvents::MAINTENANCE
Pimcore\Event\System\MaintenanceEvent
Pimcore\Model\Schedule\Manager\Procedural
Pimcore\Model\Schedule\Maintenance\Job
Pimcore\Maintenance\CallableTask
Pimcore\Model\Document\Tag\Block::enumerate()
Pimcore\Model\Document\Hardlink::setChildsFromSource()
Pimcore\Model\Document\Hardlink::getChildsFromSource()
Pimcore\Model\Document\Page::getName()
Pimcore\Model\Document\Page::setName()
Pimcore\Model\Document\Link::getName()
Pimcore\Model\Document\Link::setName()
Pimcore\Model\Document\Link::getParameters()
Pimcore\Model\Document\Link::setParameters()
Pimcore\Model\Document\Link::getAnchor()
Pimcore\Model\Document\Link::setAnchor()
Pimcore\Model\Document\Link::getTitle()
Pimcore\Model\Document\Link::setTitle()
Pimcore\Model\Document\Link::getAccesskey()
Pimcore\Model\Document\Link::setAccesskey()
Pimcore\Model\Document\Link::getRel()
Pimcore\Model\Document\Link::setRel()
Pimcore\Model\Document\Link::getTabindex()
Pimcore\Model\Document\Link::setTabindex()
Pimcore\Model\Document\Link::getTarget()
Pimcore\Model\Document\Link::setTarget()
Pimcore\Model\Tool\Targeting\Rule::fireEvent()
Pimcore::addToGloballyProtectedItems()
Pimcore::removeFromGloballyProtectedItems()
Pimcore\Placeholder::setWebsiteClassPrefix()
Pimcore\Placeholder::getWebsiteClassPrefix()
Pimcore\Placeholder::setPlaceholderPrefix()
Pimcore\Tool::clearSymfonyCache()
Pimcore\Tool::getSymfonyCacheDirRemoveTempLocation()
Pimcore\Update
Pimcore\Db\ConnectionInterface::supportsParameters()
Pimcore\Db\PimcoreExtensionsTrait::supportsParameters()
Pimcore\Cache\Pool\Redis\Connection
Pimcore\Model\Document\Tag\Area\AbstractArea::_getParam()
Pimcore\Model\Document\Tag\Area\AbstractArea::_getAllParams()
Pimcore\Model\Tool\Email\Log::getToAsArray()
Pimcore\Model\Tool\Email\Log::getCcAsArray()
Pimcore\Model\Tool\Email\Log::getBccAsArray()
Pimcore\Model\Tool\Email\Log::getReplyToAsArray()
Pimcore\Model\Document\Email::getToAsArray()
Pimcore\Model\Document\Email::getAsArray()
Pimcore\Model\Document\Email::getFromAsArray()
Pimcore\Model\Document\Email::getReplyToAsArray()
Pimcore\Model\Document\Email::getCcAsArray()
Pimcore\Model\Document\Email::getBccAsArray()
Pimcore\Model\Document\Newsletter::getFromAsArray()
Pimcore\Bootstrap::includes()
Pimcore\Http\Request\Resolver\PimcoreContextResolver::CONTEXT_INSTALL
Pimcore\Http\Response\CodeInjector::POSITION_REPLACE
Pimcore\HttpKernel\BundleLocator\BundleLocator::resolveBundlePath()
Pimcore\HttpKernel\BundleLocator\BundleLocatorInterface::resolveBundlePath()
Pimcore\Image\HtmlToImage::getXvfbBinary()
Pimcore\Model\AbstractModel::getResource()
Pimcore\Model\Dao\Mysql\AbstractMysql
Pimcore\Model\Listing\Dao\Mysql\AbstractMysql
Pimcore\Tool\Console::checkExecutingUser()
Pimcore\HttpKernel\Config\SystemConfigParamResource

# LEGACY MODE
Pimcore::isLegacyModeAvailable()
Pimcore\Model\Document\PageSnippet::doRenderWithLegacyStack()
Pimcore\Model\Document\PageSnippet::isLegacy()
Pimcore\Model\Document\PageSnippet::getLegacy()
Pimcore\Model\Document\PageSnippet::setLegacy()
Pimcore\Model\Document::doRenderWithLegacyStack()
Pimcore\ExtensionManager
Pimcore\Helper\LegacyClass
Pimcore\Model\Staticroute::getLegacy()
Pimcore\Model\Staticroute::setLegacy()
Pimcore\Model\Document\Tag\Areablock::isCustomAreaPath()
Pimcore\Model\Document\Tag\Areablock::isBrickEnabled()
Pimcore\Model\Document\Tag\Areablock::getAreaDirectory()
Pimcore\Model\Document\Tag\Areablock::getPathForBrick()
Pimcore\Model\Document\Tag\Areablock::getBrickConfig()
Pimcore\Model\Document\Tag\Areablock::getAreaDirs()
Pimcore\Model\Document\Tag\Areablock::getBrickConfigs()
Pimcore\Model\Document\Tag\Area\Info::setConfig()
Pimcore\Model\Document\Tag\Area\Info::getConfig()
Pimcore\Model\Document\Tag\Area\Info::setPath()
Pimcore\Model\Document\Tag\Area\Info::getPath()
Pimcore\Model\Document\Tag\Area\Info::setName()
Pimcore\Model\Document\Tag\Area\Info::getName()
Pimcore\Model\Document\Tag\Area::getAreaDirs()
Pimcore\Model\Document\Tag\Area::getBrickConfigs()

# Aliases
Pimcore\Glossary\Processor
Pimcore\Admin\Helper\QueryParams
Pimcore\Service\Locale
Pimcore\Localization\Locale
Pimcore\Service\IntlFormatterService
Pimcore\Service\WebPathResolver
Pimcore\Service\RequestMatcherFactory
Pimcore\Service\Context\PimcoreContextGuesser
Pimcore\Service\Request\AbstractRequestResolver
Pimcore\Service\Request\DocumentResolver
Pimcore\Service\Request\EditmodeResolver
Pimcore\Service\Request\PimcoreContextResolver
Pimcore\Service\Request\ResponseHeaderResolver
Pimcore\Service\Request\SiteResolver
Pimcore\Service\Request\TemplateResolver
Pimcore\Service\Request\TemplateVarsResolver
Pimcore\Service\Request\ViewModelResolver

# E-Commerce Framework
Pimcore\Bundle\EcommerceFrameworkBundle\FilterService\FilterType\ProxyFilter
Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\Worker\DefaultElasticSearch
Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\DefaultElasticSearch
Pimcore\Bundle\EcommerceFrameworkBundle\Legacy\LegacyClassMappingTool

Method Signature Changes

Pimcore\Templating\Renderer\IncludeRenderer::render() - removed last optional argument $legacyView

E-Commerce Framework

  • Added hierarchy between IProduct and ICheckoutable (and renamed them to ProductInterface and CheckoutableInterface)
    • will be a BC break when class signature looks like class MyClass implements CheckoutableInterface, ProductInterface,
    • no problem, when it is the other way round like class MyClass implements ProductInterface, CheckoutableInterface
  • Renamed all Interfaces to Symfony standard schema - e.g. ICart becomes CartInterface
    • BC layer for all old interfaces in place, issues deprecation warnings in IDE and logs, but it should work without problems
  • Removed Pimcore\Bundle\EcommerceFrameworkBundle\FilterService\FilterType\ProxyFilter
  • Removed Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\Worker\DefaultElasticSearch and Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\DefaultElasticSearch
  • Removed Pimcore\Bundle\EcommerceFrameworkBundle\Legacy\LegacyClassMappingTool and pimcore_ecommerce.use_legacy_class_mapping config option.
  • Removed adding environment items CheckoutManager::TRACK_ECOMMERCE and CheckoutManager::TRACK_ECOMMERCE_UNIVERSAL with tracking codes after order commit. Use Tracking Manager instead.
  • Default rounding mode of Decimal changed to PHP_ROUND_HALF_UP.

Consistent API Behavior

We've changed the behavior of many static model getters to return null instead of throwing an exception. Following there's a list of all affected methods.

Pimcore\Model\Glossary::getById()
Pimcore\Model\Notification::getById()
Pimcore\Model\Redirect::getById()
Pimcore\Model\Site::getById()
Pimcore\Model\Site::getByDomain()
Pimcore\Model\Site::getBy()
Pimcore\Model\Version::getById()
Pimcore\Model\WebsiteSetting::getById()
Pimcore\Model\DataObject\ClassDefinition\CustomLayout::getByName()
Pimcore\Model\DataObject\Fieldcollection\Definition::getByKey()
Pimcore\Model\DataObject\Objectbrick\Definition::getByKey()
Pimcore\Model\DataObject\QuantityValue\Unit::getByAbbreviation()
Pimcore\Model\DataObject\QuantityValue\Unit::getByReference()
Pimcore\Model\DataObject\QuantityValue\Unit::getById()
Pimcore\Model\Element\Recyclebin\Item::getById()
Pimcore\Model\Schedule\Task::getById()
Pimcore\Model\Tool\Tracking\Event::getById()
Pimcore\Model\Translation\AbstractTranslation::getByKeyLocalized()