Zend Framework 2: Database config - php

I'm digging into ZF2, and I've run into some confusion on how to use Zend\Config with Zend\Db to manually set up a connection.
In different places in the manual, there are db configs in different formats.
This one shows a flat array as the config format:
https://packages.zendframework.com/docs/latest/manual/en/modules/zend.db.adapter.html
$adapter = new Zend\Db\Adapter\Adapter(array(
'driver' => 'Mysqli',
'database' => 'zend_db_example',
'username' => 'developer',
'password' => 'developer-password'
));
While this one shows a nested format:
https://packages.zendframework.com/docs/latest/manual/en/modules/zend.config.introduction.html
$configArray = array(
'database' => array(
'adapter' => 'pdo_mysql',
'params' => array(
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'dbname' => 'mydatabase'
)
)
);
What I expect to happen is that I can call for a new db adapter like so, but this throws exceptions:
$config = new Zend\Config\Config(
array(
'db' => array(
'adapter' => 'Mysqli',
'params' => array(
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'dbname' => 'mydatabase'
)
)
)
);
$adapter = new Zend\Db\Adapter\Adapter($config->db);
What I end up having to do is:
$config = new Zend\Config\Config(
array(
'db' => array(
'driver' => 'Mysqli',
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'database' => 'mydatabase'
)
)
);
$adapter = new Zend\Db\Adapter\Adapter($config->db->toArray());
Is there a better way of achieving what I'm trying to achieve without having to resort to the service manager?

Ignore the example from the Zend Config introduction page, that's just showing how to make a config object from a PHP array, the structure of the array isn't meant to show anything in particular.
Since you don't want to use the service manager, you need to pass the parameters to the adapter class in the structure it expects. It expects an array, a config object won't work. You've worked out what the structure of the array is, so that's what you need to use.
I think this page in the docs: http://framework.zend.com/manual/2.3/en/tutorials/tutorial.dbadapter.html (the "Basic setup" section) gives a better explanation of the service manager approach, which is how I'd do it in an MVC app at least.

Related

Symfony Multiple Databases

I'm not asking you to help me with a code purpose, but for an advice of how to do what I've got to do.
Since a few weeks, i'm developing a web application based on the symfony3 framework, and now, I have to modify what I did because my boss wants me to open the solution on multiple "groups". In fact, the group will correspond with a database which will be the group's content for the application.
I explain with a schema:
Login page -> login / password / group
If GROUP = A, database = db_group_a (for exemple)
If GROUP = B, database = db_group_b (..)
I dont know if it's clear, but here's what I have to do, and I really dont know how to do it with Symfony (In simple PHP, I would do it quite simply, but Symfony makes me ask you). If you could help me, it would be awesome.
Thanks!
In symfony you can define multiple databases like this:
$container->loadFromExtension('doctrine', array(
'dbal' => array(
'default_connection' => 'default',
'connections' => array(
'default' => array(
'driver' => '%database_driver%',
'host' => '%database_host%',
'port' => '%database_port%',
'dbname' => '%database_name%',
'user' => '%database_user%',
'password' => '%database_password%',
'charset' => 'UTF8',
),
'group_a' => array(
'driver' => '%database_driver2%',
'host' => '%database_host2%',
'port' => '%database_port2%',
'dbname' => '%database_name2%',
'user' => '%database_user2%',
'password' => '%database_password2%',
'charset' => 'UTF8',
),
'group_b' => array(
'driver' => '%database_driver2%',
'host' => '%database_host2%',
'port' => '%database_port2%',
'dbname' => '%database_name2%',
'user' => '%database_user2%',
'password' => '%database_password2%',
'charset' => 'UTF8',
),
),
),
Now, once you logged in and found out, what group is the user privileged to, you can set that in your session and add as a parameter to queries similar to this:
$allowed_db = 'group_a';
$customers = $this->get('doctrine')
->getRepository('AcmeCustomerBundle:Customer', $allowed_db)
->findAll();

Create new database on the fly in Laravel 4

I want dynamically create new database, database user and password with privileges, create some tables in new database on the fly in Laravel 4 for every new user. This is for a multi tenant website.
Whats the best solution?
thanks.
This is not your first database connection it's easy, but you'll have to execute raw statements because database creation is no available as connection methods:
DB::statement(DB::raw('CREATE DATABASE <name>'));
To do that you can use a secondary connection:
<?php
return array(
'default' => 'mysql',
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'host1',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
),
'store' => array(
'driver' => 'mysql',
'host' => 'host2',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
),
),
);
Then you can, during application bootstrap, change the database of the secondary connection:
DB::connection('store')->setDatabaseName($store);
or
Config::set('database.connections.store', $store);
And use the secondary connection in your queries:
$user = User::on('store')->find(1);
or
DB::connection('store')->select(...);

Zend 2 + Doctrine 2 indefinite number of connections

Currently I am working on ZF2 application using Doctrine 2. The application deals with multiple users and each user has an access to the application through his own subdomain, for example:
user1.example.com
user2.example.com
...
user10.example.com
Also, each user has his own database, corresponding to his subdomain, let say:
db_user1
db_user2
..
db_user10
The configuration is quite trivial having one or two doctrine connections:
<?php
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => 'user',
'password' => 'pass',
'dbname' => 'database',
)
),
// Here we can define several configuration alternatives,
//use different keys for each one
'orm_alternative'=> array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => 'db_user1',
'password' => 'db_pass1',
'dbname' => 'db_user1',
)
),
),
)
);
Obviously in my case the above configuration is useless, since I have indefinite numbers of connections to different databases.
So, my question is what is the best way to setup Doctrine to work with indefinite numbers of connections, based on the subdomain.
Cheers,
Vasil Dakov
Config load order look like that
1.application.config.php
2.$module->getConfig()
3.$module->get{,*}Config() (or ServiceListeners)
4./config/autoload/{,.*}{global,local}.php
So You could add every user config in Module.php in getConfig() function.
public function getConfig()
{
return array(
'user1' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => 'db_user1',
'password' => 'db_pass1',
'dbname' => 'db_user1',
)
)
);
//of course you have access to service locator here and could generate your dbconfigs
}
I think the best solution for my own question is to get the EntityManager instance via Service Factory as the following example:
<?php
namespace Application\Doctrine\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
class EntityManagerServiceFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator)
{
$subdomain = array_shift(explode(".",$_SERVER['HTTP_HOST']));
$paths = array(ROOT_PATH.'/module/Application/src/Application/Entity');
$account => $this->getAccountTable()->findOneBy(array("subdomain" => $subdomain));
$isDevMode = true;
$dbParams = array(
'driver' => 'pdo_mysql',
'user' => $account['user'],
'password' => $account['password'],
'dbname' => $account['dbname'],
);
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$config = Setup::createConfiguration($isDevMode);
$driver = new AnnotationDriver(new AnnotationReader(), $paths);
AnnotationRegistry::registerLoader('class_exists');
$config->setMetadataDriverImpl($driver);
$entityManager = EntityManager::create($dbParams, $config);
return $entityManager;
}
}
It works fine and hope to help someone else.

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

doctrine 2 create database and tables [duplicate]

I would like to create a database with doctrine 2 and zend framework 2.
I tried to use the command line but it doesn't work because first of all I need to be connected to a database.
Here is the command line that I could use :
When I use the command "php doctrine dbal:run-sql CREATE DATABASE TOTO", I receive an error which tells me that I the database that I selected (but I don't want to select any database) is unknown.
Do you have any idea how I can figure out this problem ?
I really appreciate if I not obliged to use phpmyadmin and create it by my own. I'll prefer to use doctrine to make sure that my code is compatible with other kind of database (such as Mysql/Postegre)
Thank you =D
I found the solution.
You just have to specify in your configuration file that the dbname is equals to null.
<?php
return array (
'doctrine' => array (
'connection' =>
array (
'orm_default' =>
array (
'driverClass' => 'Doctrine\\DBAL\\Driver\\PDOMySql\\Driver',
'params' =>
array (
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => '',
'dbname' => null,
'charset' => 'UTF8',
),
),
'orm_poems' =>
array (
'driverClass' => 'Doctrine\\DBAL\\Driver\\PDOMySql\\Driver',
'params' =>
array (
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => 'mot de passe',
'dbname' => 'poemsV3',
'charset' => 'UTF8',
),
),
),
),
);
Have a good day everybody =D

Categories