Files

Filesystem

Filesystem service, storage path helpers, file operations a bezpečné zápisy během runtime.

Overview

Filesystem module provides three focused services: file operations (FileManagerInterface), directory operations (DirectoryManagerInterface) and lock operations (LockManagerInterface). Filesystem facade composes these services into one convenience API.

Registered services

FilesystemServiceProvider registers typed services and string aliases. Prefer typed IDs in application code; aliases are convenience access points.

$container->singleton(DirectoryManagerInterface::class, DirectoryManager::class);
$container->singleton(FileManagerInterface::class, FileManager::class);
$container->singleton(LockManagerInterface::class, LockManager::class);
$container->singleton(Filesystem::class, Filesystem::class);

$container->singleton('filesystem', static fn (ContainerInterface $container): Filesystem => $container->get(Filesystem::class));
$container->singleton('files', static fn (ContainerInterface $container): FileManagerInterface => $container->get(FileManagerInterface::class));
$container->singleton('directories', static fn (ContainerInterface $container): DirectoryManagerInterface => $container->get(DirectoryManagerInterface::class));
$container->singleton('locks', static fn (ContainerInterface $container): LockManagerInterface => $container->get(LockManagerInterface::class));

Usage through dependency injection

Dependency injection is the preferred integration style for application services.

final class ExportWriter
{
    public function __construct(
        private readonly Filesystem $filesystem,
    ) {
    }
}

File operations

Use FileManagerInterface (or the Filesystem facade) for read and metadata operations.

$path = $context->resolveCachePath('products.json');

$filesystem->write(
    file: $path,
    data: json_encode($products, JSON_THROW_ON_ERROR),
    mode: 0664,
);

$size = $filesystem->size($path);
$mime = $filesystem->mime($path);
$hash = $filesystem->hash($path, 'sha256');

Directory operations

Use DirectoryManagerInterface for create/delete/copy/write/traversal operations. Traversal methods return generators.

$filesystem->create($context->resolveWritablePath('exports'));
$filesystem->copy(
    $context->resolveWritablePath('exports'),
    $context->resolveWritablePath('exports-backup'),
    true,
);

foreach ($filesystem->stream($context->resolveLogPath(), true) as $name => $absolutePath) {
    echo $name . ' => ' . $absolutePath . PHP_EOL;
}

foreach ($filesystem->find('*.log', $context->resolveLogPath()) as $logFile) {
    echo $logFile . PHP_EOL;
}

Lock operations

LockManagerInterface executes callback code under an exclusive file lock and always releases the lock afterwards.

$result = $filesystem->lock($context->resolveWritablePath('locks/products.lock'), static function () use ($filesystem, $products, $context): int {
    $filesystem->write(
        file: $context->resolveCachePath('products.json'),
        data: json_encode($products, JSON_THROW_ON_ERROR),
    );

    return count($products);
});

Storage paths

Use ApplicationContext path helpers to keep filesystem paths runtime-safe and consistent across environments.

$cacheFile = $context->resolveCachePath('products.json');
$lockFile = $context->resolveWritablePath('locks/products.lock');
$logFile = $context->resolveLogPath('import.log');
$uploadDir = $context->resolveUploadPath('images');

Aliases in provider wiring

String aliases (filesystem, files, directories, locks) exist for provider and framework wiring where the container is explicitly available. Application services should inject typed filesystem contracts instead of resolving aliases at runtime.

$container->singleton(ExportWriter::class, static function (ContainerInterface $container): ExportWriter {
    return new ExportWriter(
        $container->get(Filesystem::class),
    );
});

Exceptions

Filesystem failures throw FilesystemException (for example file-not-found, read/write failure, lock failure). Catch it where you need explicit error handling.

use Lemonade\Framework\Filesystem\Exception\FilesystemException;

try {
    $content = $filesystem->read($context->resolveCachePath('missing.json'));
} catch (FilesystemException $exception) {
    // Handle filesystem error.
}