Setting up a db connection using variables from another file - php

I am attempting to set up a db connection for a mysqli_connect statement $dbc. I had it working in my script with the following:
DEFINE ('DB_USER','myName';
DEFINE ('DB_PASSWORD','somePass123';
DEFINE ('DB_HOST','localhost';
DEFINE ('DB_NAME','sitename';
// make the db connection
$dbc = #mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME)
OR die ('Could not connect to mysql: ' . mysqli_connect_error());
I then posted a question on SO about security and best practice and was advised that if the connection variables (password, host, dbname, user) exist elsewhere in a separate database configuration file, that I should call the variables for the connection from there.
Here is the relevant snippet from the file in config/database/php
$config['default'] = array(
'benchmark' => TRUE,
'persistent' => FALSE,
'connection' => array(
'type' => 'mysqli',
'user' => 'myName',
'pass' => 'somepass123',
'host' => 'localhost',
'port' => FALSE,
'socket' => FALSE,
'database' => 'sitename',
),
'character_set' => 'utf8',
'table_prefix' => '',
'object' => TRUE,
'cache' => FALSE,
'escape' => TRUE
);
So I then tried this:
DEFINE ('DB_USER','$config['default']['connection']['user'])';
DEFINE ('DB_PASSWORD',$config['default']['connection']['pass']);
DEFINE ('DB_HOST',$config['default']['connection']['host']);
DEFINE ('DB_NAME',$config['default']['connection']['database']);
// make the db connection
$dbc = #mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME)
OR die ('Could not connect to mysql: ' . mysqli_connect_error());
Which produced the following error when I tried to load the page:
"Undefined variable: config"
I then tried this:
$dbc = #mysqli_connect(
$config['default']['connection']['host'],
$config['default']['connection']['user'],
$config['default']['connection']['pass'],
$config['default']['connection']['database'])
OR die ('Could not connect to mysql: ' . mysqli_connect_error());
// Set the encoding
mysqli_set_charset($dbc, 'utf8');
// set the query variable
$query = "SELECT MAX(rating_date)
AS last_date
FROM rating
WHERE incident_id = $incident_id;";
//connect and run the query
$result = mysqli_query($dbc, $query);
echo $result->fetch_object()->last_date;
?>
Which then produced the following error:
"Fatal error: Call to a member function fetch_object() on a non-object in..."
I'm not 100% sure what this is telling me. Yesterday I learned that one cannot echo a SQL query in php directly because it's an object so I cut n pasted the part "echo $result->fetch_object()->last_date;" which worked.
It seems that now that I am trying to draw upon the variables from config, rather than just define them in the function, I am unable to connect perhaps due to a scope issue?
The file with the $dbc connection is in a folder themes/myname/views/reports/detail.php
The file with the database configuration details array is in application/config/database.php
It looks like an issue of variable scope?
What would be the best practice here in making my $dbc variable? How do I call the variables from database.php when it exists in a different directory than the file where I'm calling it? Must I include() the whole file?

How about something sane like:
$dbc = #mysqli_connect(
$config['default']['connection']['host'],
$config['default']['connection']['user'],
$config['default']['connection']['pass'],
$config['default']['connection']['database'])
OR die ('Could not connect to mysql: ' . mysqli_connect_error());
You don't gain anything by using define(), you're only trying to avoid putting the raw strings with your username and password into the mysqli_connect() call in case an error occurs and that line gets sent to the client in an error message/stack trace.

Constants are global and you don't need to set them as global to retrieve them from the memory but variables are not, if you are calling the variable $config from inside a function you have two ways to call it:
Set the variable to be global at the first beginning of your function that you are calling this variable from global $config;
OR
Call the variable using the $GLOBALS variable $config = $GLOBALS['config'];

Related

PHP MySQL over SSL. Peer certificate did not match

I'm trying to use Google Cloud SQL over SSL from GCE(Google Compute Engine) instance. My problem is that I cannot connect to Cloud SQL instance over SSL.
mysql command works normally. I can connect to Cloud SQL instance with certification files.
mysql -uroot -p -h [IP Address] --ssl-ca=/home/user/.cert/server-ca.pem --ssl-cert=/home/user/.cert/client-cert.pem --ssl-key=/home/user/.cert/client-key.pem
However, I got warning and fatal error as followings when I access from PHP program.
<?php
$pdo = new PDO('mysql:host=[IP Address];dbname=testdb', 'root', 'test', array(
PDO::MYSQL_ATTR_SSL_KEY =>'/home/user/.cert/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT=>'/home/user/.cert/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA =>'/home/user/.cert/server-ca.pem'
)
);
$stmt = $pdo->query("SHOW TABLES;");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($row);
?> 
 
PHP Warning: PDO::__construct(): Peer certificate CN=`[GCP project name]:[Cloud SQL instance name]' did not match expected CN=`[IP Address]' in /tmp/mysql.php on line 7
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2002] ' in /tmp/mysql.php on line 7
I got same error when I used mysqli.
$mysqli = mysqli_init();
mysqli_options($mysqli, MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true);
$mysqli->ssl_set('/home/user/.cert/client-key.pem',
'/home/user/.cert/client-cert.pem',
'/home/user/.cert/server-ca.pem',
NULL,NULL);
$mysqli->real_connect('[IP Address]', 'root', 'test', 'testdb', 3306, NULL, MYSQLI_CLIENT_SSL);
 
PHP Warning: mysqli::real_connect(): Peer certificate CN=`[GCP project name]:[Cloud SQL instance name]' did not match expected CN=`[IP Address]' in /tmp/mysql3.php on line 30
Warning: mysqli::real_connect(): (HY000/2002): in /tmp/mysql3.php on line 30
This question looks be relevant to my case but there is no answer yet. SSL self-signed certifications to connect with Mysql with PHP
Does anyone know about solutions?
Update 1
The bug is reported. https://bugs.php.net/bug.php?id=71003
Very similar question here. Google Cloud SQL SSL fails peer certificate validation
My PHP version is 5.6.14. I will update to 5.6.16 to use MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT.
Update 2
Fixed it when I use mysqli
What I did are as followings:
1 I updated my PHP to 5.6.20
sudo apt-get install php5
2 I put the MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT option like this.
$mysqli->real_connect('[IP Address]', 'root', 'test', 'testdb', 3306, NULL, MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);
My application uses both mysqli and PDO for some reasons. I'm now looking for PDO's solution.
Update 3
This bug report shows about PDO's case. Sounds not fixed yet.
https://bugs.php.net/bug.php?id=71845
This is also related. https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/google-cloud-sql-discuss/4HNvmq7MpU4/kuSjhkS2AwAJ
As far as I understand, there is no way to resolve for PDO.
Update 4
Some people blame google's design of CN names (I agree with them actually..)
What's worst is you guys use impossible CN names (:) . If the CN was without colon maybe I can map the ip and the CN in my hosts file so that when peer validation is done it can pass. With the colon, php thinks is host and is port
and Google's staff? understand the problem.
I understand the current situation when connecting by IP is not ideal.
But it seems they provide a solution called 'proxy'.
https://groups.google.com/forum/#!topic/google-cloud-sql-discuss/gAzsuCzPlaU
I'm using Cloud SQL second generation and my applications are hosted GCE. So I think I can use the proxy way. I will try it now.
Update 5
Setup the proxy access. Solved both PDO and mysqli access.
Install the proxy on Ubuntu
$ wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64
$ mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy
$ chmod +x cloud_sql_proxy
$ sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
$ ./cloud_sql_proxy -dir=/cloudsql -instances=<project name>:us-central1:mydb
PDO
<?php
$pdo = new pdo('mysql:unix_socket=/cloudsql/<project name>:us-central1:mydb;dbname=testdb','root','test');
$stmt = $pdo->query("SHOW TABLES;");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($row);
?>
mysqli
$mysqli = mysqli_connect('localhost', 'root', 'test', 'testdb', 3306, '/cloudsql/<project name>:us-central1');
$sql = "SELECT id FROM users";
if ($result = $mysqli->query($sql)) {
while ($row = $result->fetch_assoc()) {
echo $row["id"] . "\n";
}
$result->close();
}
$mysqli->close();
refs (Japanese)
http://blog.hrendoh.com/connecting-to-google-cloud-sql-using-mysql-client/
http://blog.hrendoh.com/google-appengine-php-using-cloud-sql/
For PDO connections that don't use Google cloud or cannot benefit from the proxy solution, they have fixed the bug and it is merged now.
There is now a constant for this (starting April 2017):
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
http://git.php.net/?p=php-src.git;a=commit;h=247ce052cd0fc7d0d8ea1a0e7ea2075e9601766a
In short, use Cloud SQL Proxy if you need to access from both PDO and mysqli. You have no choice.
https://cloud.google.com/sql/docs/sql-proxy
For mysqli, adding:
MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT
to real_connect() solved my instance of this issue.
Example (replace host, user, password and database as needed):
$db_connection->real_connect('ip address or host', 'user', 'password', 'database', 3306, NULL, MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);
Full php mysqli SSL connection script:
// check if openssl is enabled on server
if(!extension_loaded('openssl')) {
throw new Exception('This app needs the Open SSL PHP extension and it is missing.');
}
// start connection
$db_connection = mysqli_init();
// set ssl config (update with your certs location)
$db_connection->ssl_set('/etc/my.cnf.d/certs/client-key.pem','/etc/my.cnf.d/certs/client-cert.pem', '/etc/my.cnf.d/certs/ca-cert.pem', NULL, NULL);
// connect (update with your host, db and credentials)
$db_connection->real_connect('ip address or host', 'user', 'password', 'database', 3306, NULL, MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);
Example in CakePHP 3.5.x + PHP 7.1.x + SQL Google Cloud + SSL
Change file in: config/app.php
...
...
/**
* The test connection is used during the test suite.
*/
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'xx.xxx.xxx.xxx',
//'port' => 'non_standard_port_number',
'username' => 'user_name_x',
'password' => 'pass_x',
'database' => 'bd_name_x',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
'flags' => [
PDO::MYSQL_ATTR_SSL_KEY => CONFIG.'client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT => CONFIG.'client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA => CONFIG.'server-ca.pem',
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false
],
//'ssl_key' => CONFIG.'client-key.pem',
//'ssl_cert' => CONFIG.'client-cert.pem',
//'ssl_ca' => CONFIG.'server-ca.pem',
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
],
],
...
...
Example PHP Pure + PDO + SSL:
$ssl_key = CONFIG.'client-key.pem';
$ssl_cert = CONFIG.'client-cert.pem';
$ssl_ca = CONFIG.'server-ca.pem';
$pdo = new PDO('mysql:host=xxx.xxx.xxx.xxx;dbname=db_name_x', 'user_name_x', 'pass_x', array(
PDO::MYSQL_ATTR_SSL_KEY => '/path/full/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT => '/path/full/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA => '/path/full/server-ca.pem',
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false
)
);
$statement = $pdo->query("SHOW TABLES;");
var_dump($statement);
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo json_encode($row);
exit();
I had the same problem with a MySQL database hosted at compose cluster.
After searching and testing for hours, I found out that the best solution is to disable testing the certificate provided by the server by using the MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT flag.
I haven't tested it with PDO but with the mysqli interface it is working for me.
In general this problem would appear with a database hosted at a cluster server.

PHP - Connect to Multiple MySQL Databases

So I have a PHP page that connects first to my database and does a bunch of stuff using the information from there. Now I want to connect to another database within the same PHP page and access data from there and insert the information into my original database.
The code:
<?php
session_start();
include ("account.php");
include ("connect.php");
....
do stuff here
....
include ("account2.php");
include ("connect2.php");
...
$thing = "SELECT abc, efg, hij FROM table ORDER BY RAND() LIMIT 1" ;
$thing = mysql_query($thing);
echo "$thing";
....
....
insert information into my database
(From account.php & connect.php files)
....
?>
Everything shows up except for $thing. It says, "Invalid query: Query was empty" but I know the query I used works because when I ran it in the account2 database, I got the results I wanted. Is there something wrong with my logic or is it something else?
You are not mentioning database connection link while executing the query. May be your second database connection is defined after the 1st one in connection.php file. So interpreter is considering 2nd connection while executing the query.
Define the connection link with query,
$thing = mysql_query($thing,$conn); //$conn is your mysql_connect
You can still use the mysql_connect or similar mysql_ functions (procedural way) But all these are now deprecated. You should use mysqli_ (mysql improved) functions or go with the object oriented way.
$conn1 = new mysqli(SERVER1,DB_USER1,DB_PASS1,DB1);
$conn2 = new mysqli(SERVER2,DB_USER2,DB_PASS2,DB2);
if($conn1 ->connect_errno > 0 || $conn2 ->connect_errno > 0){
die('Unable to connect to database server.');
}
Now while executing your query,
$query = "SELECT abc, efg, hij FROM table ORDER BY RAND() LIMIT 1";
$thing = $conn1 -> query($query); //if it's second connection query user $conn2
Many web applications benefit from making persistent connections to database servers. Persistent connections are not closed at the end of the script, but are cached and re-used when another script requests a connection using the same credentials. The persistent connection cache allows you to avoid the overhead of establishing a new connection every time a script needs to talk to a database, resulting in a faster web application.
For your case, i would make 2 persistent connections, store each in it's own variable and then use one whenever i need to. Check it out using the PDO class.
//Connection 1
$dbh1 = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
PDO::ATTR_PERSISTENT => true
));
.
.
.
//Connection 2
$dbh2 = new PDO('mysql:host=localhost;dbname=test2', $user, $pass, array(
PDO::ATTR_PERSISTENT => true
));
After you finish you first database operation, then you can close the connection using
mysql_close($c) //$c = connection
And again start for next database operation.
private static function _connectDB1()
{
//give hostname, dbusername, dbpassword
$con1 = mysql_connect("localhost", "root", "rootpass");
$db1 = mysql_select_db("dbone", $con1);
}
private static function _connectDB2()
{
//if you are using different db with different credentials
//you can give here like this
// mysql_connect("mynewhost", "mynewusername", "mynewpassword")
$con2 = mysql_connect("localhost", "root", "rootpass");
$db2 = mysql_select_db("dbtwo", $con2);
}

PDO_mysql driver doesn't work

I'm using Apache server on Windows 8, XAMPP 1.8.1, PHP 5.4.7 and MySQL.
I've decided to convert my code to PDO.
Checking my phpinfo() it appears that the PDO driver for MySQL is enabled, but I still keep on getting the "could not find driver" error.
Here's the code:
<?php
//connect to database
$config['db'] = array(
'host' => 'localhost',
'username' => 'root',
'password' => '',
'dbname' => 'x'
);
$db = new PDO("
pdo_mysql:host= " .$config['db']['host']. ";
dbname= " .$config['db']['dbname']. ";
username= " .$config['db']['username'].";
password= " .$config['db']['password']."
");
?>
And the error:
Fatal error: Uncaught exception 'PDOException' with message 'could not find driver'
Any suggestions?
Let me suggest you refer to the manual page and get the proper DSN string example from there
What happens if you change the DSN prefix from pdo_mysql to just mysql?
As manual says link
You should format your dsn in this way:
DRIVER:host=YOURHOST;dbname=YOURDB
Also to create the instance you should act like this: $db = new PDO($dsn, $username, $password)
Also I forgot to say (as other users have pointed out) your DRIVER is "mysql" and not pdo_mysql
In the end there were 2 problems with the code:
1. pdo_mysql -> mysql
2. username and password should be passed as variables and not as strings.
The correct code is:
$config['db'] = array(
'host' => 'localhost',
'username' => 'root',
'password' => '',
'dbname' => 'x'
);
$db = new PDO (
"mysql:host=".$config['db']['host'].";dbname=".$config['db']['dbname']."",
$config['db']['username'],
$config['db']['password']
);

Cannot connect to Mysql database with HostGator (PHP)

I've been trying to connect to my MYSQL database on my newly acquired website through a PDO connection which is quoted below, and it doesn't seem to be working properly, as it fails as soon as I try using a query or to add an entry. All the information seems to be right, but whenever I try using any command, as selecting or adding entries, it gives me this error:
Array ( [0] => 3D000 [1] => 1046 [2] => No database selected ) 1
Here are the lines of my connection:
try {
$db = new PDO('mysql:localhost;dbname=username_dbName', 'username_dbUser', 'password');
}
catch (Exception $e) {
die('Erreur : ' . $e->getMessage());
print 'Unable to Connect. Please contact the website administrator.';
}
And here is the code I used to test if queries worked.
$req = $db->prepare('INSERT INTO testTable(number)
VALUES(:number)');
$req->execute(array('number' => 13)) or die(print_r($req->errorInfo()));
Obviously I use the actual login values for the connection, but it's not working and I can't figure why.
My website is hosted by HostGator, if that can help.
Thanks in advance for your answers!
Try this
try {
$db = new PDO('mysql:dbname=username_dbName;host=localhost', 'username_dbUser', 'password');
}
I think a problem is with localhost you indicate. Some hosting services require you to use something other than localhost. You might perhaps try 127.0.0.1 instead of it.
If it does not help and you are sure your username, password, and database parameters are all the way correct, I believe you will need to ask your hosting provider for a correct mysql server address.
in your real code is username_dbName a variable, like $username_dbName ? In that case you should use double quotes instead of single quotes.
"mysql:localhost;dbname=$username_dbName"
Try
$host = 'localhost';
$dbname = 'username_dbName';
$username = 'username_dbUser';
$pw = 'password';
$db = new PDO("mysql:host=$host;dbname=$dbname", $username, $pw);
EDIT: corrected typo
try this:
'driver' => 'mysql',
'host' => '(use the server IP address)',
'database' => '(database Name)',
'username' => '(database Username)',
'password' => '(the password you entered for that database user)',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => ''

load data infile and unbuffered queries error

I'm experimenting with loading a table from a file, and having difficulty. The code below is trying to take an existing database and copy it to a temporary table, then replace the original with imported data from a .csv file, and then I've got more work to do comparing the two tables before I let go of the temporary one. (Hints welcome if I should do this a different way). I get the error:
'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while
other unbuffered queries are active. Consider using
PDOStatement::fetchAll()...'
I've tried many of the suggestions from similar questions, but haven't cracked it yet. Thanks for your help! Here's my code:
<?php
//database connection
$data_source = 'mysql:host=localhost;dbname=myDB';
$db_user = 'root';
$db_password = 'pass';
$conn = new PDO($data_source, $db_user, $db_password,
array(PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT));
if ( isset($_GET['submit']) ){
$stmt = $conn->prepare("CREATE TEMPORARY TABLE mfsw_dupe AS SELECT * FROM mfsw_test");
$stmt->execute();
$stmt = $conn->prepare("TRUNCATE mfsw_test");
$stmt->execute();
$stmt = $conn->prepare("LOAD DATA LOCAL INFILE 'C:\\xampp\htdocs\assets\mfsw_test.csv' INTO TABLE mfsw_test
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 LINES");
$stmt->execute();
}
?>
After trying all the recommended solutions to this problem, I found that the answer was to set the PDO::ATTR_EMULATE_PREPARES option to true.
That got rid of "unbuffered queries" error, but it then started reporting a "LOAD DATA LOCAL INFILE forbidden" error on the LOAD query.
The solution to that was to set the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY option to true as well.
In short, your initial connection should look like this:
$conn = new PDO($data_source, $db_user, $db_password,
array(PDO::ATTR_EMULATE_PREPARES => true,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT));
I don't understand why these options are necessary, but they worked for me.
I have had exactly the same problem, tried everything mentioned above and a lot more and still couldn't avoid the "Cannot execute queries while other unbuffered queries are active" error.
However, after several hours of googling, I got it working - instead of using a prepared statement, or just query, I used 'exec' to run the 'LOAD DATA LOCAL INFILE' statement:
$stmt = $conn->exec($sql_import_csv);
I didn't need any of the aforementioned changes to the PDO options - this is my options array:
$options = array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_SSL_CA => "xxxxxxxx.crt.pem",
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_LOCAL_INFILE => true
);
Hope this helps someone else out there.

Categories