So verwaltest du mehrere Themes in einem Pimcore-Projekt mit dem CoreShop Theme Bundle
Das CoreShop Theme Bundle bietet eine standardisierte Lösung, um Themes in Pimcore zu bauen und zu verwalten, auch wenn man die E-Commerce-Funktionen von CoreShop gar nicht nutzt. Damit passt es zu vielen Pimcore-Projekten, von einfachen Content-Websites bis zu komplexen Multi-Site-Installationen.

Warum braucht man überhaupt mehrere Themes in Pimcore?
In manchen Projekten betreiben wir 20 oder 30 Websites innerhalb einer einzigen Pimcore-Instanz. Das kommt vor, wenn mehrere Sites oder Landingpages dasselbe Datenmodell teilen, etwa:
- Microsites oder Marketingseiten mit unterschiedlichen Layouts
- Verschiedene visuelle Themen für Web- und Printausgaben
- Getrennte Portale, die aber denselben Backend-Datenbestand nutzen
Das Theme Bundle von CoreShop sorgt für eine saubere und skalierbare Architektur, mit der solche Setups leichter zu managen sind.
So installierst und konfigurierst du das Theme Bundle
Wir setzen auf maximale Flexibilität und Wiederverwendbarkeit: Ein „Basis-Theme“ enthält allgemeine Funktionalitäten und Styles, die dann in projektspezifischen Themes erweitert werden.
1. Installation des CoreShop Theme Bundles
Führe folgenden Befehl via Composer aus:
composer require coreshop/theme-bundle:^4.0Anschließend aktivierst du es in deiner Kernel.php:
public function registerBundlesToCollection(BundleCollection $collection)
{
$collection->addBundles([
new \CoreShop\Bundle\ThemeBundle\CoreShopThemeBundle(),
]);
}2. Theme Resolver konfigurieren
CoreShop liefert mehrere „Theme Resolver“ mit. Zum Beispiel kannst du Themes über Pimcore-Dokumenteigenschaften zuweisen:
core_shop_theme:
default_resolvers:
pimcore_document_property: trueDazu weist du eine Dokumenteigenschaft namens theme zu. CoreShop versucht dann, das passende Theme anhand dieses Namens (z. B. base) aufzulösen.

Verzeichnisstruktur der Themes in Pimcore
Intern greift CoreShop auf das Sylius Theme Bundle zurück und nutzt das Dateisystem als Konfigurationsquelle. Standardmäßig sucht es in %kernel.project_dir%/themes nach composer.json-Dateien.

Jedes Theme enthält alle notwendigen Assets wie Twig-Templates, JS, CSS, Bilder und Schriften in einem eigenen Verzeichnis.
Theme-Vererbung mit Sylius
Das Sylius Theme Bundle unterstützt Theme-Vererbung. Ein Theme kann also von einem anderen Theme erben, zum Beispiel über eine composer.json-Datei:
{
"name": "cors/portal",
"description": "CORS portal theme",
"authors": [
{
"name": "CORS GmbH",
"email": "office@cors.gmbh",
"homepage": "https://www.cors.gmbh/",
"role": "TEAM"
}
],
"extra": {
"sylius-theme": {
"title": "portal",
"parents": [
"cors/base"
]
}
}
}Damit kannst du viel Redundanz vermeiden und Themes modular gestalten.
Theme-basierte Assets in Pimcore verwalten
Alle Assets, die zu einem Theme gehören, liegen in den jeweiligen Theme-Ordnern. Die Build-Tools (z. B. Webpack Encore) werden entsprechend konfiguriert, um pro Theme CSS, JS etc. zu generieren.
Webpack-Encore-Konfiguration
Jedes Theme erhält ein eigenes Build-Ziel:
webpack_encore:
output_path: '%kernel.project_dir%/public/build/base'
builds:
admin: '%kernel.project_dir%/public/build/admin'
base: '%kernel.project_dir%/public/build/base'
# Beispiel für zusätzliches Theme
# portal: '%kernel.project_dir%/public/build/portal'Symfony Asset Packages
Danach konfigurierst du noch die Symfony Asset Packages so, dass sie die Manifest-Dateien korrekt referenzieren und die passenden Pfade für jedes Theme nutzen.
framework:
assets:
json_manifest_path: '%kernel.project_dir%/public/build/base/manifest.json'
packages:
admin:
base_path: '/build/admin/'
json_manifest_path: '%kernel.project_dir%/public/build/admin/manifest.json'
base:
base_path: '/build/base/'
json_manifest_path: '%kernel.project_dir%/public/build/base/manifest.json'
# portal:
# base_path: '/build/portal/'
# json_manifest_path: '%kernel.project_dir%/public/build/portal/manifest.json'Mit dieser Konfiguration werden die Asset-Pfade dynamisch aufgelöst. Das kann z. B. eine Twig-Funktion (themeName) erledigen:
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('images/favicons/apple-touch-icon.png',cors_theme.themeName) }}">Eigene Webpack-Configs pro Theme
Für jedes Theme definierst du idealerweise eine eigene Webpack-Konfigurationsdatei, z. B. über eine Hilfsfunktion getConfig:
const Encore = require('@symfony/webpack-encore');
/**
*
* @param {string} name
* @param {string} outputPath
* @param {string} publicPath
* @param {Array.<{name:string, src:string}>} entries
* @param {Array.<{name:string, src:string}>} styleEntries
* @param {Array.<{from:string, to:string}>} copyFiles
* @param {Array.<Plugin>} plugins
* @param {boolean} defaults
* @param {boolean} mangle
* @returns {webpack.Configuration}
*/
function getConfig({
name,
outputPath,
publicPath,
entries = [],
styleEntries = [],
copyFiles = [],
plugins = [],
defaults = true,
mangle = true
}) {
Encore.reset();
if (!mangle) {
Encore.configureTerserPlugin((options) => {
return {
terserOptions: {
mangle: false,
}
};
})
}
Encore
// directory where all compiled assets will be stored
.setOutputPath(outputPath)
// what's the public path to this directory (relative to your project's document root dir)
.setPublicPath(publicPath)
.cleanupOutputBeforeBuild()
// allow sass/scss files to be processed
.enableSassLoader()
.enablePostCssLoader((options) => {
options.postcssOptions = {
path: 'postcss.config.js'
};
})
.enableSingleRuntimeChunk()
.enableSourceMaps(!Encore.isProduction())
.enableVersioning(Encore.isProduction())
.enableTypeScriptLoader()
;
// ##########################################################################################
// ### default integrations for all configs
// ##########################################################################################
if (defaults) {
// Put your default js includes here, if needed
/*Encore
.addEntry('js/base', './themes/base/assets/js/base.js')
;*/
}
entries.forEach(entry => {
if (entry.name && entry.src) {
Encore.addEntry(entry.name, entry.src);
}
})
styleEntries.forEach(entry => {
if (entry.name && entry.src) {
Encore.addStyleEntry(entry.name, entry.src);
}
})
if (defaults) {
// Put your default copyFiles here, if needed
/*copyFiles = [
...[
{
from: './themes/base/assets/images',
to: 'images/[path][name].[ext]',
}, {
from: './themes/base/assets/fonts',
to: 'fonts/[path][name].[ext]',
}
],
...copyFiles
];*/
}
Encore
.copyFiles(copyFiles)
plugins.forEach(plugin => {
Encore.addPlugin(plugin);
})
const config = Encore.getWebpackConfig();
config.name = name;
return config;
}
// export the final configuration
const admin = getConfig({
name: 'admin',
outputPath: 'public/build/admin',
publicPath: '/build/admin',
defaults: false,
mangle: false,
styleEntries: [
{
name: 'css/admin/edit',
src: './themes/base/admin/assets/css/edit.scss'
}
],
copyFiles: [
{
from: './themes/base/admin/assets/js',
to: 'js/[path][name].[ext]',
},
]
});
const base = getConfig(require('./themes/base/webpack-web.config.js'));
const portal = getConfig(require('./themes/portal/webpack-web.config.js'));
module.exports = [admin, base, portal];Eine themespezifische Config sieht dann z. B. so aus. Dadurch kannst du Themes unabhängig voneinander bauen und alle Abhängigkeiten sauber trennen.
module.exports = {
name: 'base-web',
outputPath: 'public/build/base',
publicPath: '/build/base',
plugins: [
require('./purgecss-web.config.js')
],
entries: [
{
name: 'js/project',
src: './themes/base/assets/js/web.ts'
},
...
],
styleEntries: [
{
name: 'css/project',
src: './themes/base/assets/css/web.scss'
}
],
copyFiles: [
{
from: './themes/base/assets/images',
to: 'images/[path][name].[ext]',
}, {
from: './themes/base/assets/fonts',
to: 'fonts/[path][name].[ext]',
}
],
}Fazit: Bereit für themebasierte Pimcore-Projekte
Mit dem CoreShop Theme Bundle lassen sich skalierbare, modulare und wiederverwendbare Themes für Pimcore-Projekte umsetzen, auch ganz ohne E-Commerce-Funktionalität. Das eignet sich besonders für Multi-Site-Architekturen, Portale und Content-Projekte.
Wenn du Unterstützung beim Aufsetzen deiner Theme-Struktur brauchst, melde dich gern. Weitere Details findest du in der offiziellen Dokumentation.

