3slab/vdm-library-ftp-transport-bundle
Installation:
composer require 3slab/vdm-library-ftp-transport-bundle
(Note: Prefer migrating to VdmLibraryFlysystemTransportBundle for new projects.)
Configuration:
Add to config/packages/vdm_library_ftp_transport.yaml (or merge into config/packages/messenger.yaml):
framework:
messenger:
transports:
ftp_consumer:
dsn: "ftp://username:password@ftp.example.com/path/to/files/"
options:
mode: move
ftp_options:
dirpath: "/remote/files/"
storage: "/local/processed/"
monitoring:
enabled: true
First Use Case:
src/MessageHandler/FtpFileHandler.php):
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
public function __invoke(string $filePath) {
// Process the file (e.g., parse CSV, upload to S3, etc.)
file_put_contents('/local/processed/' . basename($filePath), file_get_contents($filePath));
}
php bin/console messenger:consume async ftp_consumer -vv
File Collection Modes:
move: Files are moved to a storage directory after processing (default for idempotency).
options:
mode: move
ftp_options:
storage: "/local/processed/"
delete: Files are deleted post-processing (use cautiously for critical data).
options:
mode: delete
Monitoring Integration: Enable monitoring to log FTP operations (e.g., file transfers, errors) via VDM Library’s monitoring system:
options:
monitoring:
enabled: true
php bin/console vdm:monitoring:list
Custom DSN Formats:
ftp://user:pass@host:port/path/sftp://user:pass@host:port/path/ (requires PHP SFTP extension).Batch Processing:
#[AsMessageHandler]
public function handleBatch(array $filePaths) {
foreach ($filePaths as $path) {
// Process each file
}
}
Integration with VDM Library:
VdmLibraryBundle for structured data modeling. Example:
# config/packages/vdm_library.yaml
vdm_library:
models:
ftp_file:
path: "%kernel.project_dir%/config/vdm/ftp_file.yaml"
Laravel-Specific:
config/app.php:
'extra.bundles' => [
VdmLibrary\FtpTransportBundle\VdmLibraryFtpTransportBundle::class,
],
Artisan commands to manage consumers:
php artisan messenger:consume ftp_consumer --limit=10
Environment Variables:
Store credentials in .env:
FTP_TRANSPORT_DSN=ftp://${FTP_USER}:${FTP_PASSWORD}@${FTP_HOST}/files/
dsn: "%env(FTP_TRANSPORT_DSN)%"
Testing:
$this->messenger->setTransport('ftp_consumer', new MockTransport());
league/flysystem adapters for local testing:
$adapter = new LocalAdapter('/path/to/test/files');
$filesystem = new Filesystem($adapter);
Retry Strategy:
retry_strategy.max_retries must be 0. FTP transport ignores retries.
retry_strategy:
max_retries: 0 # <-- Critical
SFTP Dependencies:
php-sftp extension (not php-ftp).
pecl install sftp
league/flysystem-sftp as a fallback.File Permissions:
storage directory (for mode: move) is writable by the PHP process.
chmod -R 775 /local/processed/
Monitoring Overhead:
options:
monitoring:
enabled: false
Deprecation Warning:
VdmLibraryFlysystemTransportBundle for long-term support.transports:
ftp_consumer:
dsn: "flysystem://ftp://user:pass@host/path"
options:
adapter: ftp
mode: move
Connection Issues:
ftp:// vs. sftp://).ftp ftp.example.com
phpseclib (underlying library) errors.File Processing Failures:
dirpath or missing in storage.php bin/console messenger:consume ftp_consumer -vv
php bin/console vdm:monitoring:show ftp_consumer
Configuration Errors:
dirpath and storage paths are absolute (relative paths may fail).Custom FTP Executor:
# config/services.yaml
VdmLibrary\FtpTransportBundle\Executor\FtpExecutorInterface: '@app.custom_ftp_executor'
use VdmLibrary\FtpTransportBundle\Executor\FtpExecutorInterface;
use League\Flysystem\FTP\FTPConnectionOptions;
class CustomFtpExecutor implements FtpExecutorInterface {
public function connect(string $dsn): void {
// Custom logic (e.g., proxy, logging)
$options = FTPConnectionOptions::fromDsn($dsn);
$client = new \phpseclib\Net\SFTP($options['host']);
$client->login($options['username'], $options['password']);
}
}
Pre/Post-Processing Hooks:
// src/EventSubscriber/FtpFileSubscriber.php
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use VdmLibrary\FtpTransportBundle\Event\FileProcessedEvent;
class FtpFileSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
FileProcessedEvent::class => 'onFileProcessed',
];
}
public function onFileProcessed(FileProcessedEvent $event) {
// Log, transform, or validate the file
$event->setMetadata(['processed_at' => now()]);
}
}
Dynamic DSN Configuration:
$dsn = $this->ftpConfigRepository->getDsnForClient($clientId);
$transport = new FtpTransport($dsn, $options);
How can I help you explore Laravel packages today?