"Undefined method PDO::execute()" despite using prepare - php

This code has been working before, but I recently added a database class. I get the instance and connection from it:
$connection = MYSQLDatabase::getInstance()->getConnection();
$connection->prepare("INSERT INTO users etc etc.......
$insertArray = $connection->execute(array(
":username" => $_POST["username"]
));
getInstance() returns the database instance. getConnection() returns the connection property which contains:
new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASS);
So the error occurs when doing $connection->execute despite that $connection contains the database object, the connection, and the prepared statement.
How can this be?

Create a variable to store your prepared statement then execute that.
$connection = MYSQLDatabase::getInstance()->getConnection();
$statement = $connection->prepare("INSERT INTO users etc etc.......");
$insertArray = $statement->execute(array(
":username" => $_POST["username"]
));

Related

PDO Postgresql UTF8 charset

I'm looking for a way to connect to the postgresql database using UTF8 charset.
Currently, I have to send a query request after the connexion to specify the charset. It is not optimal at all...
$connect = new \PDO("pgsql:host=$this->host;dbname=$this->base", $this->user, $this->pass);
$connect->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$connect->query("SET NAMES '$this->charset'");
MySQL allows to pass a table on argument to specify the charset, I'm looking for the same thing.
$this->db = new \PDO("pgsql:host=$this->PARAM_hote;dbname=$this->PARAM_nom_bd", $this->PARAM_utilisateur, $this->PARAM_mot_passe, array(\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
$this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
Went with :
new PDO('pgsql:host=' . $db_host . ';dbname=' . $db_name . ';options=\'--client_encoding=UTF8\'', $db_username, $db_password, array(PDO::ATTR_PERSISTENT => true));
As a matter of fact, the single quote to pass the option --client_encoding=UTF8 is very important and a double one doesn't works.
You can pass 'options' key like this:
$dbh = new PDO
(
"pgsql:dbname=mydbname;host=myhost;port=5432;options='--client_encoding=UTF8'",
"username",
"password"
);
Try add params in constructor:
$connect = new \PDO("pgsql:host=$this->host;dbname=" . $this->base . ";options='-c client_encoding=utf8'", $this->user, $this->pass);
$connect->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

PHP Fatal error: Call to a member function execute() on a non-object( OPENSHIFT )

Getting this error:
PHP Fatal error: Call to a member function execute() on a non-object
while pushing new data to my openshit application.
function createAppInfo($title,$blog_link,$job_link,$description,$author,$status){
$db = dbopen();
$title = $db->real_escape_string($title);
$author = $db->real_escape_string($author);
$description = $db->real_escape_string($description);
$job_link = $db->real_escape_string($job_link);
$blog_link = $db->real_escape_string($blog_link);
$status = $db->real_escape_string($status);
$stmt = $db->prepare("INSERT INTO `app`(title,blog_link,job_link,description,author,status)
values('$title','$blog_link','$job_link','$description','$author','$status')");
$stmt->bind_param('s',$title,$blog_link,$job_link,$description,$author,$status); // bind inputs to the parameter
/* execute prepared statement */
$stmt->execute();
$stmt->close();
return true;
}
This is the code i am running, but it seems to me that Openshift is bloacking prepare or prepare is not working correctly i dont know..cause the code is working on local machine.
Also, its i change it to regular $db-query(INSERT) its working absolutely fine.
UPDATE:
dbcon.php file
<?php
function dbopen(){
$host="localhost"; // Host name
$username="**"; // Mysql username
$password="**"; // Mysql password
$db_name="***"; // Database name
$db= new mysqli($host, $username, $password, $db_name);
if (!$db)
{
die('Could not connect: ' . mysql_error());
}
return($db);
}?>
I am including this file to call dbopen()
see http://php.net/manual/fr/pdostatement.bindparam.php , there aren't as many parameters...
see #class comment: why bindparam for parameters that you already included in your request?
So maybe trying smthg like this should help? :
$stmt = $db->prepare("INSERT INTO `app` (title,blog_link,job_link,description,author,status) values(:title,:blog_link,:job_link,:description,:author,:status)");
$stmt->bind_param(':title',$title);
$stmt->bind_param(':blog_link', $blog_link);
etc...
$stmt->execute();
or simply let your prepare like you did, but forget about bind_param (but previous solution should be safer).
First of all, you do not need to use real_escape_string at all, prepared statements escapes all values automatically. Secondly, when binding your parameters, you need to specify the type for each (answer below assumes all are strings).
EDIT :
Upon doing some research, you must use the environment variables in the MYSQL cartridge when establishing a connection through openshift.
dbcon.php:
<?php
function dbopen(){
define('DB_HOST', getenv('OPENSHIFT_MYSQL_DB_HOST'));
define('DB_PORT', getenv('OPENSHIFT_MYSQL_DB_PORT'));
define('DB_USER', getenv('OPENSHIFT_MYSQL_DB_USERNAME'));
define('DB_PASS', getenv('OPENSHIFT_MYSQL_DB_PASSWORD'));
define('DB_NAME', getenv('OPENSHIFT_GEAR_NAME'));
$db= new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (!$db)
{
die('Could not connect: ' . mysql_error());
}
return($db);
}?>
MYSQL Query:
$db = dbopen();
$stmt = $db->prepare("INSERT INTO `app`(title,blog_link,job_link,description,author,status)
VALUES(?,?,?,?,?,?)");
$stmt->bind_param('ssssss',$title,$blog_link,$job_link,$description,$author,$status);
/* execute prepared statement */
$stmt->execute();
$stmt->close();

PDO error: no database selected

I'm making a register script and using PDO for the first time, but I get this error when trying to use it. The defines works fine when use MySQLi.
My code gives me this error:
Array ( [0] => SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected )
This is the code: (/register.php)
try{
$input_password_hash = password_hash($input_password, PASSWORD_DEFAULT);
$stmt = $PDO_new->prepare("SELECT user_name FROM users WHERE user_name = :username");
$stmt->bindParam(":username",$input_username);
$stmt->execute();
echo "code after exec";
//checks if user already exist in database.
if($stmt->rowCount()>0){
$error[] = "Username already exist";
echo "user is there";
}
else{
echo "user not there";
$insert = "INSERT INTO users(user_name, user_password_hash, user_email) VALUES($input_username,$input_password_hash, $input_email)";
}
} catch(PDOException $e){
$error[] = $e->getMessage();
}
This is the file for connecting to the databse: ((config/db_connect.php)
<?php
require_once($_SERVER['DOCUMENT_ROOT']."/config/db.php");
$PDO_new = new PDO("mysql:host=" . DB_HOST . ";DBName=" . DB_NAME, DB_USER, DB_PASS);
$PDO_new->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
And this is the file where I define the info for the database: (/config/db.php)
define("DB_HOST", "localhost");
define("DB_NAME", "username_databasename");
define("DB_USER", "username_admin");
define("DB_PASS", "password");
A quick test reveals that a PDO connection is case-sensitive in how it parses attributes. You use DBName when you should be using the lowercase dbname. This is not explicitly stated in the PDO::__construct() docs, as far as I can tell, but I was able to verify it testing in my own environment.
$PDO_new = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
//--------------------------------------------^^^^^^^^^^
It is unclear why you are also establishing a connection via MySQLi, as MySQLi and PDO are comparable but incompatible APIs. You generally need one or the other, not both (unless you are combining code from 2 sources that use opposite APIs).
It is recommended to wrap the new PDO() in a try/catch to catch connection errors before setting ERRMODE_EXCEPTION on it.
try {
$PDO_new = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
} catch (PDOException $e) {
// handle a connection error error
}
Finally, I would be remiss if I did not point out that you have plain variables in the INSERT statement rather than bound parameters. You should be binding values with placeholders here as you did in the first SELECT statement.
// Use placeholders please!
$insert = "INSERT INTO users(user_name, user_password_hash, user_email) VALUES(:input_username,:input_password_hash, :input_email)";
// prepare() then execute()...

Cloud SQL using mysqli error

I'm trying to output the results of a simple query using a Google Cloud SQL with a mysqli connection. I've properly set up a Cloud SQL instance and imported a SQL database. However, when I run my app, it seems to connect to the database - no errors are triggered there - but the logs show the following:
PHP Fatal error: Wrong SQL: SELECT * FROM students Error: No database selected in /base/data/home/apps/s~db-php-001/1.371796924944999585/main.php on line 18
Here's my code:
$conn = new mysqli(null,"root","",null,null,"/cloudsql/db-php-001:db-instance-001");
// check connection
if($conn->connect_error) {
trigger_error('Database connection failed: ' . $conn->connect_error, E_USER_ERROR);
}
$sql='SELECT * FROM students';
$rs=$conn->query($sql);
if($rs === false) {
trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR);
} else {
$rows_returned = $rs->num_rows;
}
Obviously, I'm triggering that error, but I'm can't figure out why. There is definitely a table named students in the database.
Anyone have any ideas?
Thanks!! Joe
You've set your database name to null. A connection is made like so:
$mysqli = new mysqli("localhost", "user", "password", "database");
The mysqli constructor can take in the following parameters (in this order):
$mysqli = mysqli($hostname, $username, $password, $database, $port, $socket);
In your case, you've set the parameters to be:
$hostname = null; //Defaults to mysqli.default_host
$username = "root";
$password = "";
$database = null; //Defaults to ""
$port = null; //Defaults to mysqli.default_port
$socket = "/cloudsql/db-php-001:db-instance-001";
To clarify, you can pass null for the database name. In the query you'd need to use the fully qualified table name (<database>.Students in your case). Or you can use the mysqli_select_db() function to select the database to use.

Reusing variables when working with PDO

I have to pull data from at least 3 databases, is there anything wrong with reusing my PDO objects?
$dbh = new PDO('mysql:host=' . $host . ';dbname=' . $db_name, $user, $password);
$sth = $dbh->prepare($query1);
// do something
$dbh = new PDO('mysql:host=' . $host2 . ';dbname=' . $db_name2, $user2, $password2);
$sth = $dbh->prepare($query2);
//do something else
Sorry for the edit but here's another consideration. With each of these I obviously should check whether or not the connection was successful and throw an exception if it wasn't:
if (!$dbh) {
$err=$dbh->errorInfo();
throw new Exception('Could not connect: ' . $err[2]);
}
I don't suppose there's a way to avoid this, unless I create all the connections at the same time and do if (!dbh1|!dbh2) { ... }. Just something else to consider.
When you assign $dbh to a new PDO() you are not technically reusing your pdo object. You are creating a new PDO instance and assigning it to a variable that you have previously used. There is nothing wrong with doing this as long as you understand what is occurring in your program.
EDIT:
I'm editing my answer to address the new question you've added to your previous question.
With each of these I obviously should check whether or not the connection was successful and throw an exception if it wasn't:
You can surround your connection attempt in a try catch which is a typical strategy for dealing with connection errors:
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=databaseName', $userName, $password);
foreach($dbh->query('SELECT * from TableName') as $row) {
print_r($row);
}
$dbh = null;
} catch (PDOException $ex) {
print "Error!: " . $ex->getMessage() . "<br />";
die();
}
?>
You can do that, but ... don't. Use another variable name (they are cheap) it will make your code much easier to understand. Heck you can (should) even use variable names that will clue you in on what database your object is connecting to, ie:
// connection to data warehouse
$dbh_dataWH = new PDO('mysql:host=' . $host . ';dbname=' . $db_name, $user, $password);
// connection to crm
$dbh_crm = new PDO('mysql:host=' . $host2 . ';dbname=' . $db_name2, $user2, $password2);
This way you will be able to re-use your connection objects, and the code in my very humble opinion will be much clearer for you or anyone else that has to maintain it.

Categories