Can I use two different environments in a Phinx migration? - php

I'm using phinx to manage my databases and I need to gather data from a database and insert it into another one.
I have defined the two environments in a config file like so:
'environments' => [
'default_database' => 'current',
'current' => [
'adapter' => 'mysql',
'host' => '127.0.0.1',
'name' => 'old',
'user' => 'root',
'pass' => '*****',
'port' => '3306',
'charset' => 'utf8',
],
'new' => [
'adapter' => 'mysql',
'host' => '127.0.0.1',
'name' => 'new',
'user' => 'root',
'pass' => '*****',
'port' => '3306',
'charset' => 'utf8',
]
],
What I'm trying to achieve is something like this:
public function up () {
// The environment is 'current' by default
$data = $this->fetchAll("SELECT * FROM old_table WHERE x");
// Change environment somehow
$this->environment('new')
$this->table('new_table')->insert($data);
}
Is this possible ? I can't find anything on the official documentation.

Looking in phinx code they do this when they execute a migration
public function executeMigration(MigrationInterface $migration, $direction = MigrationInterface::UP, $fake = false)
{
$direction = ($direction === MigrationInterface::UP) ? MigrationInterface::UP : MigrationInterface::DOWN;
$migration->setMigratingUp($direction === MigrationInterface::UP);
$startTime = time();
$migration->setAdapter($this->getAdapter());
you have setAdaptor available in a migration, so you might be able to use that. Would have prefered to write this in a comment as it's not really an answer but I didn't have enough charactors

Related

How does DataSource test in cakephp 2

We have custom DataSource and want to test that verifies the data after find method execute equals to one not customized.As I thought it, it would be possible if we can change Datasource in test code.I try many case, but I couldn't make it work.
public $default = [
'datasource' => 'CustomPostgres',
'persistent' => false,
'host' => 'localhost',
'port' => '5432',
'login' => 'hoge',
'password' => 'hogehoge',
'database' => 'prod',
'schema' => 'public',
'prefix' => '',
'encoding' => 'utf8'
];
public $test = [
'datasource' => 'CustomPostgres',
'persistent' => false,
'host' => 'localhost',
'port' => '5432',
'login' => 'hoge',
'password' => 'hogehoge',
'database' => 'test_prod',
'schema' => 'public',
'prefix' => '',
'encoding' => 'utf8'
];
public $old = [
'datasource' => 'Database/Postgres',
'persistent' => false,
'host' => 'localhost',
'port' => '5432',
'login' => 'hoge',
'password' => 'hogehoge',
'database' => 'dev',
'schema' => 'public',
'prefix' => '',
'encoding' => 'utf8'
];
public $test_old = [
'datasource' => 'Database/Postgres',
'persistent' => false,
'host' => 'localhost',
'port' => '5432',
'login' => 'hoge',
'password' => 'hogehoge',
'database' => 'test_dev',
'schema' => 'public',
'prefix' => '',
'encoding' => 'utf8'
];
//try1
$this->Model->setDataSource('test_old');
//try2
ConnectionManage::create('test_old',///);
//try3
////in fixture File and ClassRegistry:Init("Model")
$useDbConfig = "old";
////inner start::up
ClassRegistry:Init("Model");
//try4 extends model
ModelForOldSetting extends Model{
$useDbConfig = "old";
}
Above codes didn't work and it always emit error says
MissingConnectionException: Database connection "Postgres" is missing, or could not be created ,when running test however it works fine when setting default datasource Database/Postgres running local browser without test.
So, I'm really confused why Database connection "Postgres" is missing.Any idea makes me appreciate to them.
I finally found irritating and stupid irritating code by outer database.php file overrides datasources' setting.Following code works fine after appropriate settings.
ModelForOldSetting extends Model{
$useDbConfig = "dev";
$useTables = "models";
}
ClassRegistry:Init("ModelForOldSetting");
$model = $this->getMockForModel('ModelForOldSetting');

Dynamic datasources and global in Cakephp 3?

I have an application that will be used by many databases. To choose the database with the application data I have a database with the connections parameters (host, username, pass, database...)
The problem is that this dynamically created datasource does not work for the rest of the application.
Controller Code
$data = $this->request->data;
$connection = ConnectionManager::get("default");
$query = "SELECT * FROM clients WHERE client_id = ".$data['codigo'];
$result = $connection->execute($query)->fetchAll('assoc');
ConnectionManager::drop('default');
$config = ConnectionManager::config('connection', [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => $result[0]['host'],
'username' => $result[0]['username'],
'password' => $result[0]['password'],
'database' => $result[0]['database'],
'encoding' => 'utf8',
'timezone' => 'UTC',
'flags' => [],
'cacheMetadata' => true,
'log' => false,
'quoteIdentifiers' => false,
'url' => env('DATABASE_URL', null),
]);
$connection = ConnectionManager::get('connection');
ConnectionManager::alias('connection', 'default');
return $this->redirect(['controller' => 'Mains', 'action' => 'index']);
After this redirect, apparently the other controllers do not have this datasource.
It's certainly a bit unusual to be swapping databases based on contents inside request data - but generally database connection just needs to be done earlier on in Cake's initial setup, as each Controller's connection resource is already set to the default.
If you're only swapping the one time, you could manage this inside config/bootstrap.php (where Cake normally sets up it's ConnectionManager) instead.
You won't have access to $this->request, but could just grab it from $_REQUEST instead, for example:
In config/bootstrap.php, change these lines:
Cache::config(Configure::consume('Cache'));
ConnectionManager::config(Configure::consume('Datasources'));
Email::configTransport(Configure::consume('EmailTransport'));
To this:
Cache::config(Configure::consume('Cache'));
ConnectionManager::config(Configure::consume('Datasources'));
$connection = ConnectionManager::get("default");
$client = TableRegistry::get('Clients')->find()
->where(['client_id'=> $_REQUEST['client_id']])->firstOrFail();
ConnectionManager::drop('default');
$config = ConnectionManager::config('connection', [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => $client->host,
'username' => $client->username,
'password' => $client->password,
'database' => $client->database,
'encoding' => 'utf8',
'timezone' => 'UTC',
'flags' => [],
'cacheMetadata' => true,
'log' => false,
'quoteIdentifiers' => false,
'url' => env('DATABASE_URL', null),
]);
ConnectionManager::get('connection');
Email::configTransport(Configure::consume('EmailTransport'));
Edited: Switched from your raw SQL to a Table::find()

Kohana 3.3 Database::instance('name') not working

I have an issue with Kohana 3.3 and using different database configurations.
I have a config/database.php with 'default' config and 'other' like this:
return array
(
'default' => array
(
'type' => 'MySQL',
'connection' => array(
'hostname' => 'localhost',
'database' => 'database-one',
'username' => 'root',
'password' => 'password',
'persistent' => FALSE,
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
),
'other' => array
(
'type' => 'MySQL',
'connection' => array(
'hostname' => 'localhost',
'database' => 'database-two',
'username' => 'root',
'password' => 'password',
'persistent' => FALSE,
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
));
But in a Controller or Model when trying to use:
Database::instance('other');
Kohana will still use the 'default' configuration. What am I doing wrong?
Thanks!
If you would like to change currently used connection by kohana try this:
Database::$default = 'other';
From this line your code will use 'other' connection till you will switch it again to 'default' using same way.
You can also use another DB configuration once when executing the query in simple way:
DB::...->execute('other');
Or if you store your DB instance earlier:
$other = Database::instance('other');
DB::...->execute($other);
By ... I mean your query.
You need to store the connection in a variable, or the default connection will be used.
Documentation

DB::raw() always uses default database

I've been searching for a while for a solution here but no luck. I have a model named Currency which extends eloquent.
class Currency extends Eloquent {
protected $connection = 'currency';
protected $table = 'dbo.sfCXDetail';
public $timestamps = false;
public function monthlyTransactions(){
return Currency::select(array(DB::raw('COUNT(trx_number) AS Transactions'), DB::raw('MONTH(update_stamp) as TransactionsMonth')))
->whereBetween(DB::raw('DATEPART(YYYY, update_stamp)'), array(2012,2012))
->groupBy(DB::raw('YEAR(update_stamp)'))
->groupBy(DB::raw('MONTH(update_stamp)'))
->orderBy(DB::raw('YEAR(update_stamp)'))
->orderBy(DB::raw('MONTH(update_stamp)'))
->get();
}
}
The problem is, DB::raw uses the default database inside the database config file, so when I try using:
Currency::raw()
I get an error
strtolower() expects parameter 1 to be string, object given
The database I'm using can't be used as the default database. How do I use the DB::raw method with the current database in use inside the model?
This query works without error when I set the default database to 'currency', but not if I set it to use my local default mysql database.
This is in my DB config file:
'currency' => array(
'driver' => 'sqlsrv',
'host' => 'xx',
'database' => 'xx',
'username' => 'xx',
'password' => 'xx',
'prefix' => '',
),
You can try something like this:
DB::connection('specialConnection')->raw(...);
Also, you have to add another config settings for that connection like:
'currency' => array(
'driver' => 'sqlsrv',
'host' => 'xx',
'database' => 'xx',
'username' => 'xx',
'password' => 'xx',
'prefix' => '',
),
'specialConnection' => array(
'driver' => 'mySql',
'host' => 'xxx',
'database' => 'xxx',
'username' => 'xxx',
'password' => 'xxx',
'prefix' => '',
)
I could be wrong but I believe that setting the connection property as a protected property of Currency would not also set connection for the DB class.
would something like this work (I am at work at not able to test, sorry):
$db = new DB;
$db->connection = 'currency'
$db->table = 'dbo.sfCXDetail';
...
return Currency::select(array($db->raw('COUNT(trx_number) ...
...
I think it's a scope thing

Add connection to DBAL dynamically in Silex

I am writing a PHP application using the Silex framework. I'm using the Doctrine Service Provider, and I can open a connection normally as this:
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
'dbs.options' => array (
'localhost' => array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'test',
'user' => 'root',
'password' => 'root',
'charset' => 'utf8',
)
),
));
That works perfectly. What I want now is to add another database connection afterwards in my code. I know I can do it adding another element to dbs.options, but I want to do it afterwards, in the controllers (as different controllers will use different database connections).
Is that possible? I guess I could use something like DriverManager::getConnection($options, $config, $manager); but there's probably a better way to do it.
Thanks!
$conn = DriverManager::getConnection($params, $config);
this is original code to generate new connection, so what you wrote is ok
Link: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html
You can configure multiple db connections using the DoctrineServiceProvider bundled with Silex.
Replace the db.options with an array of configurations where keys are connection names and values configuration options.
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
'dbs.options' => array (
'mysql_read' => array(
'driver' => 'pdo_mysql',
'host' => 'mysql_read.someplace.tld',
'dbname' => 'my_database',
'user' => 'my_username',
'password' => 'my_password',
'charset' => 'utf8',
),
'mysql_write' => array(
'driver' => 'pdo_mysql',
'host' => 'mysql_write.someplace.tld',
'dbname' => 'my_database',
'user' => 'my_username',
'password' => 'my_password',
'charset' => 'utf8',
),
),
));
Access multiple connections in your controllers:
$app->get('/blog/{id}', function ($id) use ($app) {
$sql = "SELECT * FROM posts WHERE id = ?";
$post = $app['dbs']['mysql_read']->fetchAssoc($sql, array((int) $id));
$sql = "UPDATE posts SET value = ? WHERE id = ?";
$app['dbs']['mysql_write']->executeUpdate($sql, array('newValue', (int) $id));
return "<h1>{$post['title']}</h1>".
"<p>{$post['body']}</p>";
});
Source: http://silex.sensiolabs.org/doc/providers/doctrine.html

Categories