contao-community-alliance/composer-plugin
Composer plugin for Contao 3 extensions: installs packages from vendor into system/modules via copy/symlink so Contao can detect them. Helps keep legacy Contao 3 module structure working in Composer setups (also usable when supporting Contao 4 legacy mode).
Install the Plugin:
Add the plugin to your root project’s composer.json (not the module’s) under require-dev:
"require-dev": {
"contao-community-alliance/composer-plugin": "~3.0"
}
Run composer require contao-community-alliance/composer-plugin --dev.
Configure a Contao 3 Module:
In your module’s composer.json, set:
{
"type": "contao-module",
"require": {
"contao/core-bundle": "~3.5",
"contao-community-alliance/composer-plugin": "~2.4 || ~3.0"
},
"extra": {
"contao": {
"sources": {
"": "system/modules/your-module-name"
}
}
}
}
Install the Module:
Run composer require vendor/package-name in your root project. The plugin will:
system/modules/your-module-name.userfiles (if configured).runonce scripts (if specified).Verify Installation:
Check system/modules/ for the module files and confirm Contao detects it via the backend.
If your Laravel project integrates Contao 3 modules (e.g., for legacy support), use this plugin to:
system/modules/ is populated correctly for Contao’s autoloader.composer require contao-community-alliance/composer-plugin --dev
composer require vendor/contao-legacy-module
php artisan contao:clear-cache # If using a Contao bridge
src/ folder (for PSR-4) or flat structure (for legacy Contao autoloading).
Example:
src/
system/
modules/
your-module/
config/
dca/
templates/
composer.json:
"extra": {
"contao": {
"sources": {
"src/system/modules/your-module": "system/modules/your-module"
},
"userfiles": {
"src/system/modules/your-module/files": "your-module/files"
},
"runonce": [
"src/system/modules/your-module/runonce/update_db.php"
]
}
}
"autoload": {
"psr-4": {
"Vendor\\Module\\": "src/"
}
}
composer.json:
"require": {
"contao/core-bundle": "~3.5 || ~4.1",
"contao-community-alliance/composer-plugin": "~2.4 || ~3.0"
}
TL_CONFIG or Laravel’s environment checks to route logic:
if (version_compare(\Contao\CoreBundle\ContaoCoreBundle::VERSION, '4.0', '<')) {
// Contao 3 logic
}
composer post-install-cmd script to verify module installation:
"scripts": {
"post-install-cmd": [
"@contao-install",
"@php artisan contao:check-modules"
]
}
RUN sysctl -w fs.protected_symlinks=0 # For some Linux distros
Filesystem Conflicts:
system/modules/ may conflict with Laravel’s storage/ or bootstrap/cache/.public_path() or storage_path() to map Contao’s files/ directory:
// In a Contao module's runonce script
$filesDir = \Contao\System::getContainer()->getParameter('kernel.project_dir') . '/storage/app/public/contao-files';
symlink($filesDir, TL_ROOT . '/files');
Autoloading Conflicts:
class MyModule).ClassLoader to merge autoloaders:
// In a service provider
$loader = require __DIR__ . '/../../vendor/autoload.php';
$loader->addPsr4('Vendor\\Module\\', __DIR__ . '/../../src/system/modules/your-module');
Database Migrations:
runonce scripts for DB updates.// In a runonce script
if (Schema::hasTable('tl_your_module')) {
Schema::table('tl_your_module', function (Blueprint $table) {
$table->string('new_field')->nullable()->after('old_field');
});
}
Dynamic Module Loading: Use Laravel’s service providers to lazy-load Contao modules:
// ContaoServiceProvider.php
public function register()
{
if (file_exists($this->app->basePath('system/modules/your-module/config/autoload.php'))) {
require $this->app->basePath('system/modules/your-module/config/autoload.php');
}
}
Composer Scripts for Contao: Extend the plugin’s behavior with custom scripts:
"scripts": {
"contao-post-install": [
"php artisan contao:optimize",
"php artisan contao:clear-cache"
]
}
Trigger via:
composer contao-post-install
Plugin Not Installed in Root Project:
The contao-composer-plugin is not installed.composer.json under require-dev, not the module’s.Symlink Failures:
Failed to create symlink: Operation not permitted.php.ini): disable_functions = "".RUN sysctl -w fs.protected_symlinks=0.sources:
"sources": {
"src/system/modules/your-module": "system/modules/your-module"
}
Contao 4 vs. 3 Confusion:
version_compare(\Contao\CoreBundle\ContaoCoreBundle::VERSION, '4.0', '<') to branch logic.contao-module type.Runonce Scripts Not Executing:
runonce files are ignored.runonce are relative to the module root (not vendor/).runonce section is under extra.contao:
"extra": {
"contao": {
"runonce": ["path/to/script.php"]
}
}
Userfiles Not Copying:
userfiles section are missing after install."userfiles": {
"src/system/modules/your-module/files/images": "your-module/images"
}
files/ folder.Namespace Collisions:
Class 'YourModule' not found in Contao 3."autoload": {
"psr-4": {
"Vendor\\Module\\": "src/"
}
}
How can I help you explore Laravel packages today?