Trying to wrap my head around the new concepts of Zend Framework 2.0.
I'm trying to connect to a database, and to get that connection in a controller or model.
Nothing fancy, just the pure connection to run queries against.
So this is my current code:
//module.config.php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=DBNAME;host=HOSTNAME,
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'USERNAME',
'password' => 'PASSWORD',
),
'service_manager' => array(
'factories' => array(
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
What am I doing wrong?
Create db.local.php in your ./config/autoload folder and add the following content
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zenBlog;host=localhost',
'username' =>'root',
'password' =>'',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'service_manager' => array(
'aliases' => array(
'db' => 'Zend\Db\Adapter\Adapter',
),
),);
in your controller $this->getServiceLocator()->get('db'); to access to database.
This is how my local.php in config\autoload\local.php looks like.
<?php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=<dbname>;host=localhost',
'username' => 'root',
'password' => <your password here>,
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'service_manager' => array(
'aliases' => array(
'adapter' => 'Zend\Db\Adapter\Adapter',
),
),);
Now use this to create a database adapter:
$adapter = $this->getServiceLocator()->get('adapter');
Create a sql statetment and put in variable $sql.
Now do this:
$statement = $adapter->createStatement($sql);
$result = $statement->execute();
Hope this helps.
Related
Initially, I started to develop a web application using Zend Framework 2 and Doctrine2 with MySQL but the customer wants that the database would be Oracle. So, I have to change the database from MySQL to Oracle.
To do that, I have modified my doctrine.local.php file from this version
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' =>'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => 'user_gnsys',
'password' => '******',
'dbname' => 'gnsys',
),
'doctrine_type_mappings' => array(
'enum'=>'string'
)
),
)
)
);
To this other version ...
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\OCI8\Driver',
'params' => array(
'host' => 'localhost',
'port' => '1521',
'dbname' => 'GNSYS',
'driver' => 'oci8',
'user' => 'c##gnsys',
'password' => '********',
'servicename' => 'demo31',
),
'doctrine_type_mappings' => array(
'enum'=>'string'
)
),
)
)
);
Next, I try to validate my schema using the next command:
josecarlos#R2D2:~/Workspace/Web/gnsys$ php public/index.php orm:validate-schema
And I've got the next exit ...
How can I remove all these "Notice" that I've got on the exit? Have I forget to update another file?
I fixed the problem installing oci8 library.
I trying to configure several database connection in my global.php file. I followed this tutorial ( https://samsonasik.wordpress.com/2013/07/27/zend-framework-2-multiple-named-db-adapter-instances-using-adapters-subkey/#comments ) and was able to access the databases over the servicemanager
Now it looks like
//config/autoload/global.php
return array(
'db' => array(
//this is for primary adapter....
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf21_learn;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
//other adapter when it needed...
'adapters' => array(
'db1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2_staging;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'db2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2_test;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
),
),
'service_manager' => array(
// for primary db adapter that called
// by $sm->get('Zend\Db\Adapter\Adapter')
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
// to allow other adapter to be called by
// $sm->get('db1') or $sm->get('db2') based on the adapters config.
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
),
),
);
Now i can access the primary db by $sm->get('Zend\Db\Adapter\Adapter')
and db1 by $sm->get('db1') in the controller.
Now my question : Is it possible to load all adapters in a array so i can loop through them and pic the one i need.
On ZF2 I need to use a persistent MySQL connection and reconnect and the MySQL is gone away.
But I can not figure out where I should activate the MYSQL_OPT_RECONNECT parameter.
My db adapters are definied as follow:
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=DB_NAME;host=HOST',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
),
'username' => 'LOGIN',
'password' => 'PWD',
),
I have tried things like :
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=DB_NAME;host=HOST',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
'AUTO_RECONNECT_ON_UNSERIALIZE' => 1,
),
'options' => array(
'AUTO_RECONNECT_ON_UNSERIALIZE' => 1,
),
'username' => 'LOGIN',
'password' => 'PWD',
),
and nothing works.
How to make this mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect);
happen somewhere ?
Ok, the answer is :
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=DB_NAME;host=HOST',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
),
'options' => array(
PDO::ATTR_PERSISTENT => true',
),
'username' => 'LOGIN',
'password' => 'PWD',
),
But the use of persistant connection might not be a good fit for every one so you can also catch any "Mysql Server Gone Away Error" and proceed to a reconnect via :
$this->tableGateway->getAdapter()->getDriver()->getConnection()->disconnect();
$this->tableGateway->getAdapter()->getDriver()->registerConnection($this->getAdapter()->getDriver()->getConnection()->connect());
if($this->tableGateway->getAdapter()->getDriver()->getConnection()->isConnected()) {
return true;
}
Is it possible to make an SSL encrypted connection via ZF2 to my MySql Server?
And if yes, how is it possible?
I can't find anything for ZF2 PDO SSL connection on the web.
return array(
'db' => array(
'adapters' => array(
// The first (default) database connection
'zf2' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=zf2;host=sandbox-db-vm',
'username' => 'root',
'password' => 'password',
),
// Now the second database connection
'zf2ssl' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=zf2;host=sandbox-db-vm',
'username' => 'ssl_user',
'password' => 'ssl_test',
PDO::MYSQL_ATTR_SSL_KEY => '/etc/mysql-ssl/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT => '/etc/mysql-ssl/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA => '/etc/mysql-ssl/ca-cert.pem'
),
),
),
'service_manager' => array(
// Let's make sure our adapters get instantiated
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
),
),
);
How can I configure (and use) multiple databases in Zend Framework 2? Currently I have this in my global.php:
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=my_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'user',
'password' => '******',
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
But I do not see a way to add a second one.
If you look at the Zend\Db\Adapter\AdapterServiceFactory, you'll see that your adapter configuration points to only one key 'db'. Which means that the Adapter that it builds will always use this (unique) configuration key.
I recommend you to create your own factory that would look like this :
namespace Your\Namespace;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\Adapter;
class MyAdapterFactory implements FactoryInterface
{
protected $configKey;
public function __construct($key)
{
$this->configKey = $key;
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('Config');
return new Adapter($config[$this->configKey]);
}
}
In your main module (or any other one), add the following to the Module.php file to declare the adapters factories to the Zend Service Manager:
use Your\Namespace\MyAdapterFactory;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
class Module implements ServiceProviderInterface{
//Previous code
public function getServiceConfig()
{
return array(
'factories' => array(
'myadapter1' => new MyAdapterFactory('dbconfigkey1'),
'myadapter2' => new MyAdapterFactory('dbconfigkey2'),
),
);
}
//...
The global config should now look like:
return array(
'dbconfigkey1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=my_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'user',
'password' => '******',
),
'dbconfigkey2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=my_db2;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'user',
'password' => '******',
),
);
to use the adapters you need to call them using the Service Manager:
$adapter1=$serviceManager->get('myadapter1');
$adapter2=$serviceManager->get('myadapter2');
As of version 2.2
An Abstract Service Factory is now part of the zf2 Zend\Db module. It is possible to add multiples configuration keys under the 'adapters' sub-key :
'db'=> array(
'adapters'=>array(
'adapter' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=test;host=localhost',
'username' => 'readCredential',
'password' => '****'
),
'adapter2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=test;host=localhost',
'username' => 'rwCredential',
'password' => '****'
),
)
),
However, the AbstractServiceFactory need to be added "manually" as it isn't so by default :
'service_manager' => array(
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
)
),
The adapters are accessible as previously :
$adapter1=$serviceManager->get('adapter');
$adapter2=$serviceManager->get('adapter2');
From a performance perspective this second approach is better : One object will be instantiated (The abstract factory) to (potentially) create the different adapters. Whereas in the previous approach, one object per configuration was created.
I found much better explaination on https://samsonasik.wordpress.com/2013/07/27/zend-framework-2-multiple-named-db-adapter-instances-using-adapters-subkey/
Zend Framework 2.2 comes with abstract_factories Zend\Db\Adapter\AdapterAbstractServiceFactory that allow us to configure multiple named DB adapter instances. This is step by step to do it :
Register Zend\Db\Adapter\AdapterAbstractServiceFactory at ‘abstract_factories’ type under ‘service_manager’ key.
//config/autoload/global.php
//.... part of config/autoload/global.php
'service_manager' => array(
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
),
),
Configure ‘adapters’ subkey under ‘db’ key at config/autoload/global.php
//config/autoload/global.php
//.... part of config/autoload/global.php
'db' => array(
'adapters' => array(
'db1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2_staging;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'db2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2_test;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
),
),
Configure ‘adapters’ subkey under ‘db’ key at config/autoload/local.php
//config/autoload/local.php
return array(
'db' => array(
'adapters' => array(
'db1' => array(
'username' => 'root',
'password' => '',
),
'db2' => array(
'username' => 'other_user',
'password' => 'other_user_passwd',
),
),
),
);
Call adapter using ‘db1’ or ‘db2’ as db adapter from ServiceManager
$sm->get('db1');
$sm->get('db2');
If you need to get $sm->get(‘Zend\Db\Adapter\Adapter’) as primary adapter, ‘db1’ and ‘db2’ as other adapter for specific purpose, then you need to define primary adapter directly under db, so the configuration of config/autoload/global.php will be like the following :
//config/autoload/global.php
return array(
'db' => array(
//this is for primary adapter....
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf21_learn;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
//other adapter when it needed...
'adapters' => array(
'db1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2_staging;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'db2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2_test;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
),
),
'service_manager' => array(
// for primary db adapter that called
// by $sm->get('Zend\Db\Adapter\Adapter')
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
// to allow other adapter to be called by
// $sm->get('db1') or $sm->get('db2') based on the adapters config.
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
),
),
);
The config/autoload/global.local.php should be configured too like the following :
//config/autoload/local.php
return array(
'db' => array(
// for primary db adapter that called
// by $sm->get('Zend\Db\Adapter\Adapter')
'username' => 'root',
'password' => '',
// to allow other adapter to be called by
// $sm->get('db1') or $sm->get('db2') based on the adapters config.
'adapters' => array(
'db1' => array(
'username' => 'root',
'password' => '',
),
'db2' => array(
'username' => 'other_user',
'password' => 'other_user_passwd',
),
),
),
);