Multiple DB connections in ZF3 - database

When I was using ZF1, I had an ini file with db connection information (i.e. mysql, pgsql, mssql, etc...)
modulename.adapter = PDO_MYSQL
modulename.params.host = xxx.xxx.x.xx
modulename.params.username = username
modulename.params.password = password
modulename.params.dbname = databasename
and in my model, I would extends Zend_Db_Table and do the following in my
public function _construct() {
$dbconfig = Zend_Registry::get('dbProfiles');
$this->db = Zend_Db::factory($dbconfig->modulename->adapter,
$dbconfig->modulename->params);
}
in some function, I have the following code
$sql = "SELECT * FROM Table";
$result = $this->db->query($sql);
while($row =$result->fetch()) {
//... do something
}
How can I do something similar to this in ZF3? Connecting multiple database types, querying different tables, and fetching my results?
Thank you.

In your configuration set as many database adapters as you have databases:
'db' => [
'adapters' => [
'Application\Db\Db1Adapter' => [
'driver' => 'Pdo_Mysql',
'Dsn' => 'mysql:dbname=Your_db_1_name;host=your_host;charset=utf8',
'password' => 'your_password',
'username' => 'your_username',
],
'Application\Db\Db2Adapter' => [
'driver' => 'Pdo_Mysql',
'Dsn' => 'mysql:dbname=Your_db_2_name;host=your_host;charset=utf8',
'password' => 'your_password',
'username' => 'your_username',
]
]
],
Then call the adapter in service manager factories to create tablegateway or just pass the adapter to the controller:
use \Application\Db\Db1Adapter;
...
$db1Adapter = $container->get(Db1Adapter::class);
...

Related

Class 'yii\app\models\DB' not found in yii2

I am trying to use database connection inside my model but it was not getting connected throwing error as "Class 'app\models\DB' not found". I have created a common model to be extended by all my models inside modules that means all models extends the CommonModel, I am getting this error inside the CommonModel. I have read yii documentation regards database connection & googled for the same but I din't find any solution. My code is:
models\CommonModel.php
namespace app\models;
use Yii;
use yii\base\NotSupportedException;
use yii\db\ActiveRecord;
use yii\helpers\Security;
use yii\web\IdentityInterface;
use yii\db\Query;
use app\models\Mailsettings;
use \PDO as PDO;
class CommonModel extends \yii\db\ActiveRecord{
protected $_db;
protected $_sql;
public function __construct()
{
$this->_db = DB::init(); // This line causing the error
$pdo = Timetrackdb::getPdoConnection();
}
----
----
}
config/db.php & config/db2.php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=my_db_name',
'username' => 'db_username',
'password' => 'db_password',
'charset' => 'utf8',
];
config/web.php
$db = require __DIR__ . '/db.php';
$db2 = require __DIR__ . '/db2.php';
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'modules' => [
'my_module1' => [
'class' => 'app\modules\my_module1'
],
'my_module2' => [
'class' => 'app\modules\my_module2'
],
],
------
------
'db' => $db,
'db2' => $db2,
------
------
];
I have created 2 modules in which one module is working fine with the same type of database connection but the other module's db connection is not working properly. Can anyone please tell whats wrong with this code? Thanks.
Yii deals with connecting to databases for you, you don't need PDO. Just access Yii::$app->db2 if you want to have CommonModel or derived ActiveRecord classes to use the second database as their data store:
class CommonModel extends ActiveRecord {
public static function getDb()
{
// this will cause Yii to use the database configured as 'db2' in config/web.php
return Yii::$app->db2;
}
}
class Car extends CommonModel { }
// will try to insert a new row in `db2`.`car`
(new Car)->save();
You may also need to do the following if you're going to perform cross-schema queries (config/db2.php):
return [
// ...
// add and adjust the keys below
'tablePrefix' => '',
'schemaMap' => [
'mysql' => [
'class' => 'yii\db\mysql\Schema',
'defaultSchema' => 'my_db_name',
],
],
];

Yii2 application distribute data from one database to different databases filtered using a particular field

I want to do a module that will distribute the data of my application to different databases according to a particular attribute.
Let's say my current program collects employee information and here are the fields that I have:
db_company
tbl_employee => [id, fname, mname, lname, name_suffix, birthdate, address, sex, civil_status]
Now I want to distribute data according a particular field which is civil_status in different databases with same table structure.
db_company_single
tbl_employee => [id, fname, mname, lname, name_suffix, birthdate, address, sex, civil_status]
db_company_married
tbl_employee => [id, fname, mname, lname, name_suffix, birthdate, address, sex, civil_status]
Will it be possible using just a module or not?
Thank you.
You have to override getDb() in your model and based on static variable change the connection it returns.
Config:
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db_company_single',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
'dbMarried' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db_company_married',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
Controller:
$model = new Employee();
// Already false but it's easier to get the idea.
Employee::$isMarried = false;
$model->fname = 'Single';
$model->save();
Employee::$isMarried = true;
$model->fname = 'Married';
$model->save();
Model:
public static $isMarried = false;
public static function getDb() {
if (self::$isMarried === true) {
return Yii::$app->dbMarried;
} else {
return Yii::$app->db;
}
}
Yes, you need to switch database connections.
For your case you may need to use master-slave configurations, ad your other database connections to slave configuration, Yii2 Documentation describes it here Yii2 Master Slave
Example code
[
'class' => 'yii\db\Connection',
// configuration for the master
'dsn' => 'dsn for master server',
'username' => 'master',
'password' => '',
// common configuration for slaves
'slaveConfig' => [
'username' => 'slave',
'password' => '',
'attributes' => [
// use a smaller connection timeout
PDO::ATTR_TIMEOUT => 10,
],
],
// list of slave configurations
'slaves' => [
['dsn' => 'dsn for slave server 1'],
['dsn' => 'dsn for slave server 2'],
['dsn' => 'dsn for slave server 3'],
['dsn' => 'dsn for slave server 4'],
],
]

symfony2 doctrine.dbal.connection_factory with ssl?

I connect to a remote database from within my symfony2 app with this code
$connectionFactory = $this->container->get('doctrine.dbal.connection_factory');
$conn = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'mattias',
'password' => 'fdfsdf',
'host' => 'fs1.rrtgy.se',
'dbname' => 'csmedia',
));
return $conn;
Is there a parameter I can set to do it using SSL?
The equivalent of something like this:
$link = mysql_connect("192.112.7.18","test","testpass",false,MYSQL_CLIENT_SSL)
You could try add to createConnection array 'driverOptions'
$conn = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'mattias',
'password' => 'fdfsdf',
'host' => 'fs1.rrtgy.se',
'dbname' => 'csmedia',
'driverOptions' => array(
PDO::MYSQL_ATTR_SSL_CA =>'/path/to/ssl-ca.pem'
),
));
More info about MYSQL SSL constants.
Notice, that some constants were added at php 5.3.7
However, SSL options are silently ignored in (at least) version 5.3.8: see the bug report.

MSSQL Access From Zend2 via Linux

I'm upgrading an application that presently runs on ZendFramework1(ZF1) to ZendFramework2(ZF2). I'm having trouble getting DB results to return from the ZF2 connection.
In ZF1 this test works perfectly:
$db = Zend_Db::factory('Pdo_Mssql', array(
'host' => 'ServerNameFromFreeTdsConfig',
'charset' => 'UTF-8',
'username' => 'myUsername',
'password' => 'myPassword',
'dbname' => 'database_name',
'pdoType' => 'dblib'
));
$stmt = $db->prepare("select * from Products");
$stmt->execute();
$result = $stmt->fetchAll();
$stmt->closeCursor();
However, I've been trying this in ZF2 but I'm not really getting anywhere. In my config\autoload\global.php I have:
return array(
'db' => array(
'host' => 'ServerNameFromFreeTdsConfig',
'charset' => 'UTF-8',
'dbname' => 'database_name',
'username' => 'myUsername',
'password' => 'myPassword',
'driver' => 'pdo',
'pdodriver' => 'dblib',
),
);
And in the Module.php file:
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$config = $e->getApplication()->getServiceManager()->get('Configuration');
$dbAdapter = new Adapter($config['db'], new SqlServer());
GlobalAdapterFeature::setStaticAdapter($dbAdapter);
}
Then in the Model\Products.php
class Products extends AbstractTableGateway
{
protected $table;
protected $featureSet;
public function __construct($table = 'Products') {
$this->table = $table;
$this->featureSet = new FeatureSet();
$this->featureSet->addFeature(new GlobalAdapterFeature());
$this->initialize();
}
//Test the connection.
public function getProducts() {
$result = $this->getAdapter()->query("select * from Products", Adapter::QUERY_MODE_EXECUTE);
die(var_dump($result));
}
}
It looks like it is connecting because the "var_dump" above returns a ["fieldCount":protected]=> int(7) which is correct (there are 7 columns in that table). However, it is not returning any results.
What might I need to do to get this to work in ZF2? Do I need to somehow extend Zend\Db\Adapter\Adapter using code from the ZF1 Zend_Db_Adapter_Pdo_Mssql.php file? Or is there some simple solution I'm missing?
Thanks for any insight.
I think you dont need to mention the user name and password
resources.db.adapter = "sqlsrv"
resources.db.host = "localhost\SQLEXPRESS"
resources.db.dbname = "DatabaseName"
resources.db.isDefaultTableAdapter = true
resources.db.driver_options.ReturnDatesAsStrings = true
I ended up writing my own Adapter adopted from the Zend Framework 1 adapter I had working there. If someone comes across this post looking for a solution to the same problem and would like a copy of the code I transposed, let me know. There is quite a lot of code or I'd post it here.

How Can I Read the DB Configuration Settings From a Cake Shell?

I would like to write a cake shell to do a nightly backup of my database using mysqldump. I could do this as a shell script, but if I can cram it into a CakePHP shell, then I will get the added benefit of it working across both the development and live server, if I can get it to automagically read my database config settings. I will cron the cake shell and have some peace-of-mind knowing that I have frequent backups of my DB.
In my shell I'm trying to build up a string which starts with "mysqldump --user=" and I'd like to get the username from app/config/database.php. How can I get at the data in database.php?
In cake 2.1 the format has changed to:
App::uses('ConnectionManager', 'Model');
$dataSource = ConnectionManager::getDataSource('default');
$username = $dataSource->config['login'];
The following snippet should do the trick:
App::import('Core', 'ConnectionManager');
$dataSource = ConnectionManager::getDataSource('default');
$username = $dataSource->config['login'];
In CakePHP 3.x the format has changed to -
use Cake\Datasource\ConnectionManager;
$source = ConnectionManager::get('default');
debug($source); #Debugging the result
Result :
object(Cake\Database\Connection) {
'config' => [
'password' => '*****',
'username' => '*****',
'host' => '*****',
'database' => '*****',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
'url' => null,
'name' => 'remote'
],
'driver' => object(Cake\Database\Driver\Mysql) {
'connected' => false
},
'transactionLevel' => (int) 0,
'transactionStarted' => false,
'useSavePoints' => false,
'logQueries' => false,
'logger' => null
}
Get the Result :
debug($source->config()); #Accessing the result
Result :
[
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'username',
'password' => 'password',
'database' => 'database',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
'url' => null,
'name' => 'remote'
]
Just for sharing.
For any cakephp project, if using php as cronjob or command line to do large data processing I would build a standalone php script without cakephp, the reason for doing this because cakephp is slow (e.g. read & process 100K records).
To make my life simple I put all my standalone scripts under app/Vendor/myscripts/ (e.g: app/Vendor/myscripts/process.php)
below also the basic code to make sure you use the same database settings in standalone script with cakephp (tested with MySQL)
require_once '/XYZ/app/Config/database.php';
$database = new DATABASE_CONFIG;
try{
$dblink = new PDO('mysql:host='.$database->default['host'].';dbname='.$database->default['database'], $database->default['login'], $database->default['password'], array(PDO::ATTR_PERSISTENT => false));
$dblink->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dblink->exec('SET CHARACTER SET '.$database->default['encoding']);
} catch (Exception $e) {
die('DB Error'. $e->getMessage());
}
Example in controller, Change multi DB for DataSources in CakePHP 2.5.x
App::uses('AppController', 'Controller');
class DemoController extends AppController {
public $uses = array('AppModel', 'GVA21', 'GVA01', 'GVA14', 'GVA24' );
public function test_dbs(){
$this->autoRender=false;
// Load ConnectManager
App::uses('ConnectionManager', 'Model');
// DataSource ['default']
$MDM = $this->GVA14->find('count');
echo "MDM.GVA14\n<br>";
debug($MDM);
// Get DataSource Config DB ['default'] and ['SRL']
$confDeafult = ConnectionManager::$config->default;
$confSrl = ConnectionManager::$config->SRL;
// Change DataSource ['SRL']
ConnectionManager::drop('default');
ConnectionManager::create('default',$confSrl); //<== Is permanet change Find All models Down
// $this->GVA01->setDataSource('SRL'); //<== Is temp change Find model
echo "SRL.GVA14\n<br>";
$SRL = $this->GVA14->find('count');
debug($SRL);
$SRL = $this->GVA01->find('count');
echo "SRL.GVA01\n<br>";
debug($SRL);
$SRL = $this->GVA21->find('count');
echo "SRL.GVA21\n<br>";
debug($SRL);
// Change to DataSource ['default']
debug(ConnectionManager::drop('default'));
ConnectionManager::create('default',$confDeafult); //<== Is permanet change Find All models Down
//$this->GVA01->setDataSource('default'); //<== Is temp change Find model
$MDM = $this->GVA01->find('count');
echo "MDM.GVA01\n<br>";
debug($MDM);
$MDM = $this->GVA21->find('count');
echo "MDM.GVA21\n<br>";
debug($MDM);
////FIN
exit('FIN');
}

Resources