I am creating a database for each user who has a record. I am able to set this created database via config. But I can't migrate.
The error I encountered is:
Database [5d7acdf5adf6a] not configured.
$user=User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'database'=>uniqid()
]);
Artisan::call('make:database',['dbname'=>$user->database]);
$this->connectAnother($user->database);
Artisan::call('migrate',['--database'=>$user->database]);
dd(Artisan::output());
error-->Database [5d7acdf5adf6a] not configured.
connectAnother is a method I wrote.
public function connectAnother($database){
\Config::set("database.connections.mysql", [
"host" => "127.0.0.1",
"database" => $database,
"username" => "...",
"password" => "..."
]);
}
config/database.php:
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
I tried to migrate directly when I changed the database, but got the answer 'Nothing to migrate'
Here is the solution
public function connect($database){
$connection = [
'driver' => 'mysql',
'url' => config('database.connections.mysql.url'),
'host' => config('database.connections.mysql.host'),
'port' => config('database.connections.mysql.port'),
'database' => $database,
'username' => config('database.connections.mysql.username'),
'password' => config('database.connections.mysql.password'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => 'InnoDB',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
];
\Config::set("database.connections.{$database}", $connection);
DB::setDefaultConnection($database);->***The most important place in this line***
Related
I have a multitenant application, below I have 2 connections defined, one is the default that is used by the application and the other is one that is used to access the central database while I am on the tenant connection.
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'central_mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => 'hybrid_central',
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
Below is how I would normally access the central database from the tenant.
$u = User::on('mysql')->where(['username' => $this->credentials['username']])->get()->first();
Is there a way I can call a specific database in eloquent and preform an operation on it?
e.g
If have two databases named Aaron and Mike is there a way I can call Aaron in eloquent?
Currently i use the package cooperl/laravel-db2 for the database connection. For my project, i should to toggle schema database.
I try this in db2.php :
'connections' => [
'ibmi_1' => [
...
'host' => '***********',
'username' => '***********',
'password' => '***********',
'database' => 'database',
'prefix' => '',
'schema' => 'schema_1',
'port' => *****,
'date_format' => 'Y-m-d H:i:s',
...
],
'ibmi_2' => [
...
'host' => '***********',
'username' => '***********',
'password' => '***********',
'database' => 'database',
'prefix' => '',
'schema' => 'schema_2',
'port' => *****,
...
],
And this in .env
DB_CONNECTION=ibmi_1
DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
DB_CONNECTION=ibmi_2
DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
But when i try in tinker
DB::connection('ibmi_2')
I have this error
InvalidArgumentException with message 'Database connection [ibmi_2] not configured.'
What is wrong ?
The problem was that the database configuration wasn't in bootstrap/cache/config.php.
As you all know, in Laravel config/database.php is bunch of arrays and values. But for certain condition, I need to do some logic there and I manage to do some simple logic in config/database.php and it is working as what I want (can refer the code below), but I'm wondering is it fine/practical to do like this?
If it is not practical, can you suggest what is the other way to get the same result as below?
'connections' => [
'mysql' => (function(){
$config = [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'live_db'),
'username' => env('DB_USERNAME', 'myuser'),
'password' => env('DB_PASSWORD', '2309423234'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => 'gn_',
//'prefix_indexes' => true,
'strict' => false,
'engine' => env('DB_ENGINE', null),
];
// do some logic here (and it's working!!)
// but........
// is it okay to do like this?
if(env('DB_WITH_SSLMODE', false)){
$config += [
'sslmode' => env('DB_SSLMODE', 'prefer'),
'options' => [
PDO::MYSQL_ATTR_SSL_CA => env('DB_OPT_MYSQL_ATTR_SSL_CA', 'C:\wamp64\bin\cloudsql\certificates\server-ca.pem'),
PDO::MYSQL_ATTR_SSL_CERT => env('DB_OPT_MYSQL_ATTR_SSL_CERT', 'C:\wamp64\bin\cloudsql\certificates\client-cert.pem'),
PDO::MYSQL_ATTR_SSL_KEY => env('DB_OPT_MYSQL_ATTR_SSL_KEY', 'C:\wamp64\bin\cloudsql\certificates\client-key.pem'),
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('DB_OPT_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', false)
],
];
}
return $config;
})(),
],
What about using ternary operator? (almost like it's done by default in laravel 5.8).
Note: The first solution doesn't remove the sslmode from the config array. If you need to do so, just go with the second option!
1) It should work like this:
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'sslmode' => env('DB_WITH_SSLMODE') ? env('DB_SSLMODE','prefer') : null,
'options' => (extension_loaded('pdo_mysql') && env('DB_WITH_SSLMODE')) ? [
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
PDO::MYSQL_ATTR_SSL_CERT => env('MYSQL_ATTR_SSL_CERT'),
PDO::MYSQL_ATTR_SSL_KEY => env('MYSQL_ATTR_SSL_KEY'),
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')
] : [],
],
],
or
2) dirty solution but with one conditional:
'connections' => [
'mysql' => array_merge([
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null
], (extension_loaded('pdo_mysql') && env('DB_WITH_SSLMODE')) ? [
'sslmode' => env('DB_SSLMODE', 'prefer'),
'options' => [
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
PDO::MYSQL_ATTR_SSL_CERT => env('MYSQL_ATTR_SSL_CERT'),
PDO::MYSQL_ATTR_SSL_KEY => env('MYSQL_ATTR_SSL_KEY'),
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')
]
] : [ 'options' => [] ]),
],
Then move the default values you had in env() to your .env file (note that I removed the DB_OPT_ prefix):
DB_WITH_SSLMODE=true
MYSQL_ATTR_SSL_CA=C:\wamp64\bin\cloudsql\certificates\server-ca.pem
MYSQL_ATTR_SSL_CERT=C:\wamp64\bin\cloudsql\certificates\client-cert.pem
MYSQL_ATTR_SSL_KEY=C:\wamp64\bin\cloudsql\certificates\client-key.pem
MYSQL_ATTR_SSL_VERIFY_SERVER_CERT=false
So if you set DB_WITH_SSLMODE to false, an empty array would be returned and ssl would not be enabled.
Note: I think the sslmode you specified is needed only for PostgreSQL connections, which is not your case.
You can create a service provider for this:
class SSLServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot(Kernel $kernel)
{
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$config = \Config::get('database.connections.mysql');
if (env('DB_WITH_SSLMODE', false)) {
$config += [
'sslmode' => env('DB_SSLMODE', 'prefer'),
'options' => [
\PDO::MYSQL_ATTR_SSL_CA => env('DB_OPT_MYSQL_ATTR_SSL_CA',
'C:\wamp64\bin\cloudsql\certificates\server-ca.pem'),
\PDO::MYSQL_ATTR_SSL_CERT => env('DB_OPT_MYSQL_ATTR_SSL_CERT',
'C:\wamp64\bin\cloudsql\certificates\client-cert.pem'),
\PDO::MYSQL_ATTR_SSL_KEY => env('DB_OPT_MYSQL_ATTR_SSL_KEY',
'C:\wamp64\bin\cloudsql\certificates\client-key.pem'),
\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('DB_OPT_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', false)
],
];
}
\Config::set('database.connections.mysql', $config);
}
}
and don't forget to register your service provider in config/app.php
App\Providers\SSLServiceProvider::class,
Actually you can also do something as simple as:
$database = [
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'live_db'),
'username' => env('DB_USERNAME', 'myuser'),
'password' => env('DB_PASSWORD', '2309423234'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => 'gn_',
//'prefix_indexes' => true,
'strict' => false,
'engine' => env('DB_ENGINE', null),
]
]
];
if(env('DB_WITH_SSLMODE', false)){
$database['connections']['mysql'] += [
'sslmode' => env('DB_SSLMODE', 'prefer'),
'options' => [
PDO::MYSQL_ATTR_SSL_CA => env('DB_OPT_MYSQL_ATTR_SSL_CA', 'C:\wamp64\bin\cloudsql\certificates\server-ca.pem'),
PDO::MYSQL_ATTR_SSL_CERT => env('DB_OPT_MYSQL_ATTR_SSL_CERT', 'C:\wamp64\bin\cloudsql\certificates\client-cert.pem'),
PDO::MYSQL_ATTR_SSL_KEY => env('DB_OPT_MYSQL_ATTR_SSL_KEY', 'C:\wamp64\bin\cloudsql\certificates\client-key.pem'),
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('DB_OPT_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', false)
]
];
}
return $database;
Can somebody help me, how can i run my tests, but they will interact with database copy or a virtual database. I know, that i need to use phpunit.xml file, but how? Give me a example please.
I have found a workaround for this.
In your config/database.php bellow mysql add:
'mysql_testing' => [
'driver' => 'mysql',
'host' => env('TESTING_DB_HOST', 'localhost'),
'database' => env('TESTING_DB_DATABASE', 'forge'),
'username' => env('TESTING_DB_USERNAME', 'forge'),
'password' => env('TESTING_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
And now in your .env add the values for:
TESTING_DB_HOST=localhost
TESTING_DB_DATABASE=homestead_testing
TESTING_DB_USERNAME=homestead
TESTING_DB_PASSWORD=secret
Now you can run
php artisan migrate —database=mysql_testing
And the last thing - open your phpunit.xml file in the app folder and add this:
<env name="DB_CONNECTION" value="mysql_testing"/>
<?php
return [
// other stuff
'default' => env('DB_DEFAULT', 'mysql'),
'connections' => [
'sqlite_testing' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
// other stuff
];
For controller
public function createApplication()
{
putenv('DB_DEFAULT=sqlite_testing');
$app = require __DIR__ . '/../../bootstrap/app.php';
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
return $app;
}
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
}
public function tearDown()
{
Artisan::call('migrate:reset');
parent::tearDown();
}
#pardeep in test\CreatesApplication trait there is just one function
add this putenv('DB_DEFAULT=sqlite_testing');
I wanted to ask, if is possible to work with 2 databases in cakephp3, using raw sql ?
I have query like this:
select * from shop.brochures b, upload.documents up where b.doc_id = up.id;
The problem is, this are 2 databases.
I don't know, how setup connection, i think that will not work ( doc example )
$conn = ConnectionManager::get('default');
Thank You for any advice.
in /config/app.php you can set as many db as you want; i have 2.
'Datasources' => [
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'root',
'password' => '',
'database' => 'sisarticulos',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
],
'gente' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'root',
'password' => '',
'database' => 'sggeneral',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,´
then in the controller you can set
$conn = ConnectionManager::get('default');
//some code
$conn = ConnectionManager::get('get');
use default first and then use gente