laravel
laravel copied to clipboard
No database selected when backup dynamic database
Hello, i tried to backup my database dynamically but i got error no database selected, this is my code, i run this via console command
foreach($clients as $client) {
Config::set('database.connections.tenant', array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => $client->db_name,
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
));
Artisan::call('db:backup', [
'--database' => 'tenant',
'--destination' => 'local',
'--destinationPath' => 'backup/database/' . $client->db_name,
'--compression' => 'gzip'
]);
}
Error message
[BackupManager\ShellProcessing\ShellProcessFailed]
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysqldump: Got error: 1046: No database selected when selecting the database
NOTE :
- i also check that my database
$client->db_name
is exists - i successfully backup my database if i use mysqldump
- if i put database name in config file it's work, but i need to run my code like my example above
- i think the problem is when i call
Artisan::call('db_backup')
it's not see my setup above
i'm using Backup Manager v1.1.2 and Laravel 5.1
@martiendt firstly which multi-tenancy package are you using ?
I see that you are setting the dynamic connections config which is correct , But u cannot use artisan cli while running the backup since artisan runs a different instance (i think as per my understanding). What I suggest is try to run the backup using Manager instance.
if you are running this in any controller inject the Manager into the __construct & Don't forget to type hint the Manager and Destination Facades.
use BackupManager\Manager;
use BackupManager\Filesystems\Destination;
Class Controller {
var $manager;
public function __construct(Manager $manager){
$this->manager = $manager;
}
public function backup() {
foreach($clients as $client) {
Config::set('database.connections.tenant', array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => $client->db_name,
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
));
$this->manager->makeBackup()->run('tenant', [new Destination('local', ''backup/database/' . $client->db_name,')], 'gzip');
}
}
}
This is what i would have done.
Yea, I wouldn't in general call an artisan command using Artisan::call()
I'm not saying it's a bad idea. But, I prefer to design in such a way that either my web or command-line interfaces can interact with a SEPARATE instance that then does the work.
If you inject the manager you should have no problems.
Same issue. Used the code above (tweaked for my multi-tenancy code) but still not working. Can't set the database during runtime.
Is there any solution to this issue? I am having the same problem with my multi-tenancy app.
I'm open to solutions. Got anything in mind?
The stand-alone "driver" has details necessary for using it in any circumstance. The library is infinitely extendable so new procedures and tasks can be created as well.
Let me know if you have thoughts.
This may not be the best solution, but I got this to work.
I've created an environment variable in the database config to specify the database name.
...
'tenant' => [
'driver' => 'mysql',
....
'database' => env('DB_TENANT_DATABASE'),
....
],
Then in the place where I switch the database, I check if the app is running in console and write the name of the database to the .env
file
$databaseName = 'tenant_2'; // change this to you dynamic config
if (App::runningInConsole())
{
$this->writeEnvironmentFileWith($databaseName);
}
Here is the function to write to the .env
file
protected function writeEnvironmentFileWith($key)
{
file_put_contents(app()->environmentFilePath(), preg_replace(
"/^DB_TENANT_DATABASE=(.+)/m",
'DB_TENANT_DATABASE='.$key,
file_get_contents(app()->environmentFilePath())
));
}
This hasn't been fully tested or the best solution but works.