Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Database Backup Bundle Laravel Package

symandy/database-backup-bundle

Symandy DatabaseBackupBundle provides simple database backup and restore tooling for Symfony apps. Configure your connection, create dumps from the console, and schedule automated backups so your data stays protected and can be recovered quickly when needed with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

A blunt framing first, because it changes every step after: this is a Symfony bundle, not a Laravel package. There is no service provider, no config/database-backup.php, no package auto-discovery, no artisan command registered for you. composer require symandy/database-backup-bundle will succeed (Laravel already ships the Symfony components it depends on), but nothing will be wired up. Your job is to decide whether to bridge it into Laravel or lift the dump logic out of it.

Where to look first, in this order, inside vendor/symandy/database-backup-bundle/:

  1. composer.json — the exact autoload namespace, and critically the symfony/* version constraints. Last release was 2023-04, so it targets Symfony 6.2/6.3-era components; check composer why-not symfony/console before promising anything to your team.
  2. src/Command/ — the real API surface. Run list-style discovery or just read the classes to get the command names, arguments, and options. This is the contract you'll actually use.
  3. src/DependencyInjection/Configuration.php — every config key, its default, and whether it expects a scalar, an array, or a %env()% placeholder. This file is the documentation.
  4. Resources/config/services.yaml — the service IDs and constructor arguments you'd have to reproduce if you bridge via the container.

Minimal first use case: nightly mysqldump of the app database to S3, with a matching restore path for local debugging. Don't attempt to invoke this from a controller or a queued job. Pick one of two entry points:

  • You already run a Symfony console app (sidecar, internal tool, monorepo service): register the bundle in config/bundles.php, add a YAML config block, and you're done. This is the intended path and the only one with zero friction.
  • Pure Laravel: boot a Symfony\Component\Console\Application inside an Artisan command and add the bundle's command classes to it. Roughly:
// app/Console/Commands/DbBackup.php
public function handle(): int
{
    $console = new \Symfony\Component\Console\Application('db', '1.0');

    // see src/Command/ for the real class + constructor deps
    $console->add(new BackupCommand(/* connection params, dumper, filesystem */));

    $input  = new \Symfony\Component\Console\Input\ArrayInput(['command' => 'symandy:database:backup']);
    $output = new \Symfony\Component\Console\Output\BufferedOutput();

    return $console->run($input, $output) === 0 ? self::SUCCESS : self::FAILURE;
}

The honest assessment: this bundle is thin. If you read src/ and find it's essentially "build a mysqldump argv, shell out via Process, write the file," strongly consider reimplementing that in ~40 lines inside a Laravel command rather than paying the Symfony DI tax forever. Bridge it if you need the restore path or the config-driven multi-connection behavior.

Implementation Patterns

1. Artisan wrapper → Symfony console. The lowest-risk integration: keep the bundle's command classes intact, register them on a standalone Application, and expose a thin Artisan facade. You get Schedule::command() compatibility and --option pass-through without touching the container.

// routes/console.php
Schedule::command('db:backup --connection=mysql')
    ->dailyAt('02:00')
    ->withoutOverlapping()
    ->onFailure(fn () => Log::error('db backup failed'));

2. Service-provider bridge (only if you need the services elsewhere). Translate the bundle's YAML config into a Laravel config array and rebind the services:

public function register(): void
{
    $this->app->singleton(BackupManager::class, function ($app) {
        $cfg = config('database-backup');           // your config/database-backup.php
        return new BackupManager(
            $cfg['dumps_path'],
            $cfg['connections'][$cfg['default']],
            new ProcessBuilder(),
        );
    });
}

Watch out: the bundle's Symfony config uses %env(DB_HOST)%-style placeholders which do not resolve through Laravel's env(). You'll be doing the substitution yourself.

3. Pipe the dump into Laravel's filesystem instead of a local path. The bundle likely writes to a local directory. The cleanest adaptation is to capture the output (BufferedOutput or the Process stdout) and push it through Storage::disk('s3')->writeStream(). That keeps backups on your existing Laravel disks and lets you reuse retention/rotation logic you already have.

4. Pre-deploy / pre-migration snapshot. Wrap php artisan migrate in a command that runs the backup first, and abort the deploy on a non-zero exit code. This is the single highest-value day-to-day use — far more than nightly cron.

5. CI and E2E fixtures. For integration tests that need a realistic DB, use the restore path to load a known dump into a throwaway schema. This is where multi-connection config (one for fixtures, one for prod) earns its keep.

6. Debugging workflow. Reproduce failures outside Laravel entirely: vendor/bin/… console invocation with -vvv will surface the underlying mysqldump stderr, which your Artisan wrapper will otherwise swallow. Always tee stderr to a log file in the wrapper.

Gotchas and Tips

  • Auto-discovery will not fire. If you composer require and expect php artisan list to show anything, you'll waste an hour. Register explicitly or not at all.
  • Symfony version drift is your #1 install risk. A 2023-04 release pinned against Symfony 6.2/6.3 may conflict with the symfony/console Laravel 11 resolved. Check composer why-not before you design around it. If it conflicts, the "lift the logic out" path is no longer optional.
  • Client binaries must exist on the host. mysqldump / pg_dump must be on PATH for whatever user runs PHP-FPM or the scheduler — that's a different user than your shell. Verify with sudo -u www-data which mysqldump.
  • Version mismatch between mysqldump and the server produces silent truncation on some MySQL 5.7→8.x combos. Pin or at least assert the client version at command startup.
  • Credentials on the command line are visible in ps. If the bundle passes -p<password> directly, prefer a --defaults-extra-file containing the credentials, created in a tempnam() file and unlinked in a finally. Worth checking src/ for this specifically — many small bundles get it wrong.
  • Large dumps will blow up if anything buffers. Confirm the bundle streams via Process stdout rather than building a string. If it's string-based, set memory_limit explicitly and cap at a few hundred MB, or switch to streaming in your wrapper.
  • %env()% vs env(). Symfony resolves env placeholders at container-build time with its own rules (resolve:, default:, bool: prefixes). Passing Laravel's env() values in as plain strings is usually fine, but "true" staying a string is a classic bug.
  • Locale/encoding. mysqldump output can be mangled by a non-UTF-8 locale on the host; set LC_ALL=C in the Process env array if you see corrupted non-ASCII data on restore.
  • Restore is destructive and has no safety rail. Whatever the bundle does, wrap it in a confirm() prompt for non---force invocations, and hard-refuse when app()->isProduction() unless --force is passed.
  • Zero dependents, five stars. There is no Stack Overflow corpus, no GitHub issue history to grep, no blog posts. You are reading src/ yourself. Budget for it up front; don't assume "it must support X."
  • Extension points. You almost certainly can't decorate the internal service cleanly from Laravel, so subclass the command class or, better, own the orchestration in your Artisan command and call only the bundle's leaf operations.
  • Testing. Don't hit a real binary in unit tests. Assert on the argv array the command constructs, and mock Symfony\Component\Process\Process at the boundary; keep one slow integration test that does a real dump/restore against a disposable schema.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums