This feature is available in Contao 4.13 and later.
The new filesystem capabilities are currently considered experimental and therefore not covered by Contao’s BC
promise. Classes marked with @experimental
should be considered internal for now. Although not likely, there could
also be some behavioral changes, so be prepared.
The filesystem consist of many components:
League\Flysystem\FilesystemAdapter
),Contao\CoreBundle\Filesystem\MountManager
, where adapters are mounted,Contao\CoreBundle\Filesystem\Dbafs\DbafsInterface
),Contao\CoreBundle\Filesystem\Dbafs\DbafsManager
, where DBAFS services are registered,Contao\CoreBundle\Filesystem\VirtualFilesystemInterface
) as consumer endpoints.In case of our DBAFS implementation (Contao\CoreBundle\Filesystem\Dbafs\Dbafs
), each instance also needs an individual
hash generator (Contao\CoreBundle\Filesystem\Dbafs\Hashing\HashGeneratorInterface
).
We need this level of detail to support all use cases, but wanted to offer a convenient way to add and adjust the setup
in your extensions and applications. That’s why we added a FilesystemConfiguration
class, that gets constructed with a
ContainerBuilder
instance and provides convenience methods that orchestrate everything you need in the background.
To use the FilesystemConfiguration
in your bundle, implement the ConfigureFilesystemInterface
in your extension
class:
// src/DependencyInjection/MyFooBundleExtension.php
namespace My\FooBundle\DependencyInjection;
use Contao\CoreBundle\DependencyInjection\Filesystem\ConfigureFilesystemInterface;
use Contao\CoreBundle\DependencyInjection\Filesystem\FilesystemConfiguration;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
class MyFooBundleExtension extends Extension implements ConfigureFilesystemInterface
{
public function configureFilesystem(FilesystemConfiguration $config): void
{
// Configure the filesystem here
}
// …
}
In your application in the Contao Managed Edition, you’ll need to adjust the global manager plugin instead by
implementing the ConfigPluginInterface
and creating the FilesystemConfiguration
yourself. Because plugins are
handled before extensions, we need to register a compiler pass (can be an anonymous class):
// src/ContaoManager/Plugin.php
namespace App\ContaoManager;
use Contao\CoreBundle\DependencyInjection\Filesystem\FilesystemConfiguration;
use Contao\ManagerPlugin\Config\ConfigPluginInterface;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class Plugin implements ConfigPluginInterface
{
public function registerContainerConfiguration(LoaderInterface $loader, array $managerConfig)
{
$configureFilesystemPass = new class implements CompilerPassInterface {
public function process(ContainerBuilder $container)
{
$config = new FilesystemConfiguration($container);
// Configure the filesystem here
}
};
$loader->load(static function (ContainerBuilder $container) use ($configureFilesystemPass) {
$container->addCompilerPass($configureFilesystemPass);
});
}
}
addVirtualFilesystem | Add a new virtual filesystem. Setting the $name to ‘foo’ will create a contao.filesystem.virtual.foo service and additionally enable constructor injection with an argument VirtualFilesystemInterface $fooStorage if autowiring is available. The $prefix defines the directory the instance should be scoped to. Optionally setting $readonly to true will prevent mutations being made to resources and metadata. |
mountAdapter | Creates a new adapter and mounts it under the given $mountPath in the MountManager . The $adapter and $options can be set analogous to the configuration of the Flysystem Symfony bundle. Alternatively you can pass in an id of an already existing filesystem adapter service. If you do not set a $name , the id/alias for the adapter service will be derived from the mount path. |
mountLocalAdapter | Use this shortcut method if you want to create a local adapter. Internally this is using mountAdapter but already resolves project root relative paths and parameter placeholders for you. |
registerDbafs | Registers a custom $dbafs service definition in the DbafsManager under a given $pathPrefix . |
addDefaultDbafs | Creates a default DBAFS implementation as a service and internally calls registerDbafs on it. We recommend to use this method if the default implementation fits your needs. Set the $tableName and $hashFunction to be used and optionally disable tracking last modified states by setting $useLastModified to false. |
When using addVirtualFilesystem
and addDefaultDbafs()
, the preconfigured Definition
is returned. If you want to
tweak it (e.g. if you want to adjust the DBAFS defaults), just add methods calls yourself:
// Manually adjust a configuration, if needed
$config
->addDefaultDbafs(…)
->registerMethodCall('setMaxFileSize', [1048576])
;
Here is how you could make your automatic database backups be stored on a remote server via SFTP. The first two arguments are directly passed to the Flysystem adapter (see Flysystem docs for more information):
// Mount an SFTP adapter to `/backups`.
$config->mountAdapter(
'sftp',
['host' => 'example.com', 'port' => 22, 'username' => 'foobar', 'password' => 's3cr3t'],
'backups'
);
Currently there are a lot of filesystem operations in Contao that do not use the new filesystem abstraction yet. So you
should not expect file operations to be routed to your adapter when remounting /files
for instance. The backups from
the above example are an exception to this as they are already refactored.