Skip to content

Instantly share code, notes, and snippets.

@phillipsharring
Forked from kkiernan/MySqlDump.php
Last active October 9, 2023 13:11
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save phillipsharring/fb500556e7173a1c222d to your computer and use it in GitHub Desktop.
Save phillipsharring/fb500556e7173a1c222d to your computer and use it in GitHub Desktop.
Laravel Artisan command to perform MySQL Dump using database connection information in the .env file. Posted 2016 Jan. Unsupported. Forked from https://gist.github.com/kkiernan/bdd0954d0149b89c372a
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
\App\Console\Commands\Inspire::class,
// add the MySqlDump command here
\App\Console\Commands\MySqlDump::class,
];
// etc...
}
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class MySqlDump extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'db:dump';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Runs the mysqldump utility using info from .env';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$ds = DIRECTORY_SEPARATOR;
$host = env('DB_HOST');
$username = env('DB_USERNAME');
$password = env('DB_PASSWORD');
$database = env('DB_DATABASE');
$ts = time();
$path = database_path() . $ds . 'backups' . $ds . date('Y', $ts) . $ds . date('m', $ts) . $ds . date('d', $ts) . $ds;
$file = date('Y-m-d-His', $ts) . '-dump-' . $database . '.sql';
$command = sprintf('mysqldump -h %s -u %s -p\'%s\' %s > %s', $host, $username, $password, $database, $path . $file);
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
exec($command);
}
}
@phillipsharring
Copy link
Author

phillipsharring commented Jan 14, 2016

Extra credit: add checks/smart defaults for the .env variables (like 'forge' or 'homestead' for the db name); throw if any info is missing; allow overriding those values from the command line with optional arguments; check for the mysql path; throw if the command fails; add some success output; drop in a snippet to schedule it in app/Console/Kernel schedule function; make it a composer package. Go forth!

2022 Nov update - I have not updated this code since it was written 2016 Jan. It may not be compatible with recent versions of Laravel and it is not supported. Feel free to fork it and build out the extra credit (above) or make any fixes necessary.

@kkiernan
Copy link

kkiernan commented Mar 1, 2016

Ooo brilliant!

@nicolasfuentes
Copy link

Beatiful! Thanks!!

@cesarcharaco
Copy link

cesarcharaco commented Jan 18, 2018

sorry, my problem is ..... don't execute the command, use xampp in window, show nothing...... I use laravel 5.4

@lalustine7
Copy link

mysqldump is not recognized
How can i go to mysqldump directory and run the command from the artisan?
Help me

@fmendozaro
Copy link

Thanks!

@michug
Copy link

michug commented Apr 24, 2018

I need to create an SQL dump from an artisan command in Laravel 4.2, how can I achieve this?

@Splode
Copy link

Splode commented Jun 5, 2018

Thanks!

@jeff-h
Copy link

jeff-h commented Feb 20, 2019

Without wanting to spoil anyone's fun, you should probably check what goes in the logs if this code fails for any reason. I have something similar and found it logging the full credentials to my database when an exception occurs. Even worse is that I have my site coded to email me when there's an exception, and when this dump code throws an exception I get an email containing the error, which contains the full database credentials in the clear. Oops!

@mattkenefick
Copy link

Refactoring tip for lines 43, 44 and 45: shorthand Ternary Operator (?:)

is_dir($path) ?: mkdir($path, 0755, true);

Short isn't always better. In this case, I would hesitate to condense a conditional + method into a one liner just because we can; it's not as readable.

@adelmazza
Copy link

Thanks a lot!!!
Just changed env() with config() in order to avoid caching issues

$host = config('database.connections.mysql.host'); $username = config('database.connections.mysql.username'); $password = config('database.connections.mysql.password'); $database = config('database.connections.mysql.database');

@maureknob
Copy link

Very nice!!

but my backup file ended like this:
Usage: mysqldump [OPTIONS] database [tables]
OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
OR mysqldump [OPTIONS] --all-databases [OPTIONS]
For more options, use mysqldump --help

What do i need to change in order to get especific tables?

@bynicolas
Copy link

@maureknob looks like you've been using config:cache. Laravel won't read the .env file when config:cache is used. So you need to use the config helper instead to access cached environment variables

From the docs
https://laravel.com/docs/9.x/helpers#method-env
https://laravel.com/docs/9.x/helpers#method-config

@philharmonie
Copy link

philharmonie commented Nov 3, 2022

I'm geeting 'Access denied; you need (at least one of) the PROCESS privilege(s) for this operation' when trying to dump tablespaces when I try to use this with laravel 9 in sail on dev

Edit:
With $command = sprintf('mysqldump -h %s -u %s -p\'%s\' %s --no-tablespaces > %s', $host, $username, $password, $database, $path . $file); it is working

@Patabugen
Copy link

Thanks @philharmonie !

Curiously I had the same error that you were getting (Access Denied) but when I switched to using the Symfony process control it worked as expected 🤷‍♀️ This does mean I load the whole file into memory, which could be an issue with large databases.

My slightly different version, using config instead of env and adding the port (because I have a custom port).

A bonus of using Process is that we could also check if it worked, and do something differently if it didn't.

use Symfony\Component\Process\Process;


        $host = config('database.connections.mysql.host');
        $username = config('database.connections.mysql.username');
        $password = config('database.connections.mysql.password');
        $database = config('database.connections.mysql.database');
        $port = config('database.connections.mysql.port');
        
        $process = new Process([
            'mysqldump',
            '-h', $host,
            '-P', $port,
            '-u', $username,
            '-p'.$password,
            $database,
        ]);
        $process->run();

         // Note: I actually use Storage::put() and a fixed filename to output, but for consistency with the rest of this Gist I've
         // put this untested version in:
         
        $ts = time();

        $path = database_path() . $ds . 'backups' . $ds . date('Y', $ts) . $ds . date('m', $ts) . $ds . date('d', $ts) . $ds;
        $file = date('Y-m-d-His', $ts) . '-dump-' . $database . '.sql';

        file_put_contents($path, $process->getOutput());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment