How to get php-native handle from Doctrine\DBAL\Connection? - php

Given the code
$connectionParams = array(
'dbname' => $this->dbname,
'user' => $this->dbuser,
'password' => $this->dbpass,
'host' => $this->dbhost,
'driver' => 'mysqli',
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
var_dump($conn);
How can I get the underlying mysqli handle from $conn (which is a Doctrine\DBAL\Connection)?
I have found *a way* to access it, but its obviously not the way it's supposed to be done, so I'm up for suggestions:
$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
foreach((array)$conn->getWrappedConnection() as $mysqli){
// TODO: find official way of getting the handle.
// here we are casting it to (array) to access its PRIVATE PROPERTIES
// it's a fugly hack.
break;
}
var_dump($mysqli);

You can get it this way:
$mysqli = $conn->getWrappedConnection()->getWrappedResourceHandle();

Related

Is it possible to convert a connection object to an array in PHP

I'm wondering if it's possible to convert a database connection object to an array in PHP? I've been researching, it seems you can cast an object as an array, but it doesn't seem to work for a connection object. Here's my script:
<?php
$dbHost="host";
$dbUser="user";
$dbPass="";
$dbName="root";
$dbConn = mysqli_connect($dbHost,$dbUser,$dbPass,$dbName);
$dbParts = (array) $dbConn;
for ($i=0;$i <=3; $i++){
echo $dbParts[$i];
}
?>
Any help would be greatly appreciated!
**[EDIT]**Why I need to access the db connection as an array is because I need to be able to call certain urls in a script, based on what database I'm connected to, as each environment has a different database.
Build your own array:
$db['localhost'] = array('host' => 'localhost',
'user' => 'root',
'pass' => '****',
'name' => 'database1');
Then if needed add the connection to it:
$db['localhost']['conn'] = mysqli_connect($db['localhost']['host'],
$db['localhost']['user'],
$db['localhost']['pass'],
$db['localhost']['name']);
Other possibilities depending on your needs; define the database as the lookup key:
$db['database1'] = array('host' => 'localhost',
'user' => 'root',
'pass' => '****',
'name' => 'database1');
Or define the environment:
$db['production'] = array('host' => 'localhost',
'user' => 'root',
'pass' => '****',
'name' => 'database1');
Well after a little digging I found this ( Tested ).
It relies on you having access to $dbConn.
You can get the database name being used, using something like...
$result=mysqli_query($dbConn,'SELECT DATABASE() as dbName');
$rows = mysqli_fetch_assoc($result);
var_dump($rows);
which you'd probably turn into a function to make it useful along the lines of...
function getDatabaseName($databaseConnection){
$result=mysqli_query($databaseConnection,'SELECT DATABASE() as dbName');
$row = mysqli_fetch_assoc($result);
return $row['dbName'];
// var_dump($rows);
}
$currentDatabase = getDatabaseName($dbConn);
echo $currentDatabase;
You'll have to play with this to suit...

Set autocommit off at doctrine config level

I am aware that I can switch this off at mysql level as part of its config. This is limiting as its once per instance, and I dont want to switch on and off/introduce docker to circumvent it.
However, I would like to specify this at configuration level, ie in the array that you pass to doctrine when instantiating the object, so I can have one config that rolls every back at the end of the PHP run:
$conn = array(
'driver' => 'pdo_sqlite',
'path' => __DIR__ . '/db.sqlite',
'autocommit' => false // <- Does this exist?
);
$entityManager = EntityManager::create($conn, $config);
The best I can come up with is to grab the entity manager and switch autocommit off in the setUp() and tearDown() functions, it would be nice to not to have to remember to do that or specify globally. That, and I can do ad-hoc operations outside of phpunit and get the auto rollback.
It's not tested, but you could try the following
$db = new PDO('sqlite:dogsDb_PDO.sqlite', $user, $pass, array(
PDO::ATTR_AUTOCOMMIT => false
));
$config = new \Doctrine\DBAL\Configuration();
$connectionParams = array(
'dbname' => 'mydb',
'user' => 'user',
'password' => 'secret',
'host' => 'localhost',
'pdo' => $db,
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);
$entityManager = EntityManager::create($conn, $config);
Source / simillar issue - https://github.com/doctrine/dbal/issues/2315
You could do something like:
/** #var EntityManagerInterface */
private $em;
public function setUp()
{
// initialize the entity manager in some manner .....
$this->em->beginTransaction();
}
public function tearDown()
{
$this->em->rollback();
}
Hope this help

Unable to connect to php database with pdo

I am writing a database class which is going to connect to my pdo database. This class is using this config file to get the information needed:
<?php
return [
'host' => '127.0.0.1',
'username' => 'root',
'password' => '',
'database_name' => 'books',
'database_type' => 'mysql',
'options' => []
];
And this is the database class:
<?php
class DB
{
public static function connect($config)
{
try {
return new PDO([
$config['database_type'] . ':host=' . $config['host'] . ';dbname=' . $config['database_name'],
$config['username'],
$config['password'],
$config['options']
]);
} catch(PDOException $e) {
die($e->getMessage());
}
}
}
I am getting this error:
Fatal error: Uncaught TypeError: PDO::__construct() expects parameter
1 to be string, array given in and etc...
I am wondering what I did wrong, sicne I don't see any syntax mistakes in my code.
You have an extra set of brackets:
return new PDO([
...
]);
... shouldn't have the [ and ] respectively; they're turning your four function parameters into a single array parameter. You want simply
return new PDO(
...
);
HTH!

Cakephp set database timezone

I'm setting timezone to php and mysql to internacionalize my CakePHP application.
When the server receives a request from a client, before process request, it connects to a GeoIp location server and gets the Timezone. Then I use date_default_timezone_set() to set php timezone. The problem comes up when I want to set database timezone. Once Cakephp connected, I need to execute sql query like SET time_zone='-06:00'.
In /lib/Cake/Model/Datasource/Database/Mysql.php I can see at connect() function the following code:
try {
$this->_connection = new PDO(
$dsn,
$config['login'],
$config['password'],
$flags
);
$this->connected = true;
if (!empty($config['settings'])) {
foreach ($config['settings'] as $key => $value) {
$this->_execute("SET $key=$value");
}
}
} catch (PDOException $e) {
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => $e->getMessage()
));
}
There is a $config['settings'] array that can be configured to do it. But I don't know how to fill settings array and where it's the best place to do that.
What I need is modify default datasource config on-the-fly
You can add an additional key to config array located at app/Config/database.php like this:
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'db_user',
'password' => 'db_pass',
'database' => 'db_name',
'prefix' => '',
'settings' => array(
'time_zone' => "'+01:00'", // note the quotes!
)
);
Related: CakePHP switch database (using same datasource) on the fly?
I solved it in the following way.
First of all, adding setOptions() method into DATABASE_CONFIG class as follows:
public function setOptions ($datasource, array $options){
$this->{$datasource} = array_merge($this->{$datasource}, $options);
}
Afterwards, extending ConnectionManager class to initialize it:
class ConnectionManagerCustomConfig extends ConnectionManager
{
public static function initialize(){
self::_init();
}
}
Now I initialize the class and add new options:
ConnectionManagerCustomConfig::initialize();
$configClass = ConnectionManagerCustomConfig::$config;
$configClass->setOptions('default', array(
'settings' => array(
'time_zone' => $offset
)
));

Is it possible to use Doctrine with persistent PDO connections?

I'm trying to improve performance on a volkszaehler.org implementation by enabling persistent DB connections. Having hacked included Doctrine's Connection class to have PDO::ATTR_PERSISTENT => true, I'm getting the PDO error General error: PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances"
Is there any way to fix this?
You could pass your own PDO instance to Doctrine, setting the persistent connection yourself:
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
PDO::ATTR_PERSISTENT => true
));
$config = new \Doctrine\DBAL\Configuration();
$connectionParams = array(
'dbname' => 'mydb',
'user' => 'user',
'password' => 'secret',
'host' => 'localhost',
'pdo' => $dbh,
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);
Be sure to know the implications of using persistent connections with PDO: What are the disadvantages of using persistent connection in PDO

Categories