Installers
Besides being enabled, bundles may need to execute installation tasks in order to be fully functional. This may concern tasks like
- creating database tables
- creating or updating class definitions
- importing translations
- updating database tables or definitions after an update to a newer version
- ...
To give bundles full control over their install routines, Pimcore only defines a basic installer interface which must be
implemented by your installer. The methods implemented by your installer is triggered from from commands like pimcore:bundle:install
. The basic installer
interface can be found in InstallerInterface which
is implemented in AbstractInstaller
which you can use as starting point.
A pimcore bundle is expected to return an installer instance in getInstaller()
. This method can also return null
if you
don't need any installation functionality. In this case, actions which would be handled by an installer will not be triggered
by the command pimcore:bundle:install
.
It's recommended to define the installer as service and to fetch it from the container from your bundle class on demand.
As example:
services:
App\Installer:
public: true
<?php
namespace App;
use Pimcore\Extension\Bundle\AbstractPimcoreBundle;
class App extends AbstractPimcoreBundle
{
public function getInstaller(): Installer
{
return $this->container->get(Installer::class);
}
}
Migrations
A common tasks in evolving bundles is to update an already existing/installed data structure to a newer version while also supporting fresh installs of your bundle. To be able to apply versioned changes (migrations), Pimcore integrates the Doctrine Migrations Bundle which provides a powerful migration framework. For details how to work with migrations, please have a look at the Doctrine Migrations Bundle documentation.
Pimcore Specifics
Pimcore added an additional option (--prefix=
) to the migration commands of Doctrine, to be able to filter the migration versions
for a specific namespace. This gives you the possibility to control which migrations should be executed or not.
A typical use case for that would be to just run the Pimcore core migrations or just the migrations for a specific bundle.
To make sure, the migration command only executes migrations from installed Pimcore bundles, it is recommended to extend
the bundle migrations from Pimcore\Migrations\BundleAwareMigration
and implement the getBundleName
method.
This abstract class checks if the given bundle is installed and skips the migration if necessary.
Console Examples
# only run migrations for the Pimcore core
./bin/console doctrine:migrations:migrate --prefix=Pimcore\\Bundle\\CoreBundle
# list migrations for the CMF bundle
./bin/console doctrine:migrations:list --prefix=CustomerManagementFrameworkBundle\\Migrations
# run all migrations
./bin/console doctrine:migrations:migrate
Config Examples (config.yaml
)
doctrine_migrations:
migrations_paths:
'Pimcore\Bundle\DataHubBundle\Migrations': '@PimcoreDataHubBundle/Migrations'
'CustomerManagementFrameworkBundle\Migrations': '@PimcoreCustomerManagementFrameworkBundle/Migrations'
SettingsStore Installer
The SettingsStoreAwareInstaller
adds the following functionality to the
default AbstractInstaller
:
- Manage installation state with Settings Store (instead of checking executed migrations).
- Optionally mark certain migrations as migrated during install.
- Reset migration state of migrations (if there are any) during un-install.
Implementation
For using the SettingsStore Installer extend from the SettingsStoreAwareInstaller
and implement standard install
and uninstall
methods. At the end of these methods either call the corresponding parent method or call
$this->markInstalled()
/ $this->markUninstalled()
to make sure SettingsStore is updated properly.
If during install migrations upto a certain migration should be marked as migrated during install without actually executing
them, then also implement the getLastMigrationVersionClassName
method that returns the fully qualified class name of the
last migration that should be marked as migrated.
This is useful, when install routine already does all the necessary things that also would be done by the migrations.
<?php
namespace Pimcore\Bundle\DummyBundle;
use Pimcore\Bundle\DummyBundle\Migrations\Version20210304111225;
use Pimcore\Extension\Bundle\Installer\SettingsStoreAwareInstaller;
class Installer extends SettingsStoreAwareInstaller
{
public function getLastMigrationVersionClassName(): ?string
{
// return fully qualified classname of last migration that should be marked as migrated during install
return Version20210304111225::class;
}
public function install(): void
{
//do your install stuff
$this->markInstalled();
//or call parent::install();
}
public function uninstall(): void
{
//do your uninstall stuff
$this->markUninstalled();
//or call parent::uninstall();
}
}
Pimcore\Bundle\DummyBundle\Installer:
public: true
arguments:
$bundle: "@=service('kernel').getBundle('PimcoreDummyBundle')"
Installation
During installation of the bundle following things will happen:
- All statements of the
install
method are executed. - If implemented correctly, the bundle is marked as installed in the SettingsStore.
- If configured, all defined migrations are marked as migrated (without actually executing them).
Uninstallation
During uninstallation of the bundle following things will happen:
- All statements of the
uninstall
method are executed. - If implemented correctly, the bundle is marked as uninstalled in the SettingsStore.
- Execution state of all bundle migrations that were already migrated will be reset (without actually executing them).
Migrations
Working with migrations is the same as described in the Migration section above.
For further details please see