I have done this before but am quite new to mysqli and prepared statements (as I'm sure you can see from this issue).
Where am I going wrong?
here is my connection function (part of the 'Connect' class)
public function site_db()
{
// Connect to MySQL
$link = mysqli_connect(SITE_HOST, SITE_ID, SITE_PW, SITE_DB);
// Check for Errors
if(mysqli_connect_errno())
{
//echo mysqli_connect_error(); //shouldnt show client specific error information.
die('Error connecting to mysql database please report.');
}
}
Heres the function which is causing the error:
public function exists ($what, $who)
{
$query = "SELECT * FROM users WHERE ? = ?";
// Get instance of statement
$stmt = $mysqli->stmt_init();
// Prepare query
if($stmt->prepare($query))
{
// Bind Parameters
$stmt->bind_param("ss", $what, $who);
// Execute statement
$stmt->execute();
// Bind result variables
$stmt->bind_result($result);
// Fetch Value
$stmt->fetch();
// catch num_rows result as variable
$username_result = $result->num_rows;
// Close Statement
$stmt->close();
}
if ($username_result != 0)
{
return true;
echo 'true';
}
else
{
return false;
echo 'false';
}
}
the error I get:
PHP Fatal error: Call to a member function stmt_init() on a non-object in somefile.php on line X
It is referring to the line:
$stmt = $mysqli->stmt_init();
am I making a stupid error here? Howcome I can't call that?
EDIT//
NOTE: I didn't make this very clear, but these two functions are within different classes.
public function site_db()
{
// Connect to MySQL
$mysqli = mysqli_connect(SITE_HOST, SITE_ID, SITE_PW, SITE_DB);
// Check for Errors
if(mysqli_connect_errno())
{
//echo mysqli_connect_error(); //shouldnt show client specific error information.
die('Error connecting to mysql database please report.');
}
return $mysqli;
}
public function exists (Mysqli $mysqli, $what, $who)
{
$query = "SELECT * FROM users WHERE ? = ?";
// Get instance of statement
$stmt = $mysqli->stmt_init();
// Prepare query
if($stmt->prepare($query))
{
// Bind Parameters
$stmt->bind_param("ss", $what, $who);
// Execute statement
$stmt->execute();
// Bind result variables
$stmt->bind_result($result);
// Fetch Value
$stmt->fetch();
// catch num_rows result as variable
$username_result = $result->num_rows;
// Close Statement
$stmt->close();
}
if ($username_result != 0)
{
return true;
echo 'true';
}
else
{
return false;
echo 'false';
}
}
How to use:
Instantiate first class that have site_db() method
$db = new Class();
Then instantiate second class that have exist() method
$query = new Class();
Then simply
$query->exist($db->site_db(), $what, $who );
it's because your $mysqli is not declared inside function exists(). Try a global $mysqli inside function exists() if your $mysqli is declared outside the function.
Or, probably better - make $mysql an new object inside your Connect class:
$this->mysqli = mysqli_connect(SITE_HOST, SITE_ID, SITE_PW, SITE_DB);
and in your function exists()
$stmt = $this->mysqli->stmt_init();
Related
My PHP-coded JOIN fails My SQL JOIN is fine as it works from the SQL command line - but while my PHP code will return one or more records from a single table, it fails when I JOIN with:
Uncaught Error: Call to a member function get_result() on array
My environment:
Windows 8.1.6
10.4.24-MariaDB
Apache/2.4.53 (Win64)
libmysql - mysqlnd 8.1.6
OpenSSL/1.1.1n PHP/8.1.6
The following query works from the sql command line. It is the one I would like PHP to resolve for me:
SELECT productoptionsr.contentnamekey,content.contentname LEFT JOIN content ON productoptionsr.contentnamekey=content.contentnamekey FROM productoptionsr WHERE businessnamekey='8c9007ab5e9942a80b19887057511d7b1f3c5bbea8672dc03f4fd8291f6c18ab' AND ponamekey='c91bafa8aebfb760547c761110441790f263d3c23721a5034b4d26e97b231668' ORDER BY seq;
My PHP code (a library that I put together in part using code from php.net help text)
function DBExecute($DB, $sql)
{ // A wrapper to prepare, execute a query and return $stmt
//////////////////////////////////////////////////////////////////////////////
global $sql_request;
$sql_request=$sql;
//////////////////////////////////////////////////////////////////////////////
try { $stmt = $DB->prepare($sql); }
catch (Exception $e)
{ // Handle the error, something went wrong
error_log($e->getMessage());
return DBState($DB, [ "errno"=>$e->getCode(), "error"=>$e->getMessage() ]);
}
try { $stmt->execute(); }
catch (Exception $e)
{ // Handle the error, something went wrong
error_log($e->getMessage());
return DBState($DB, [ "errno"=>$e->getCode(), "error"=>$e->getMessage() ]);
}
return $stmt;
}
function DBSelect($DB, $table, $selection, $conditions, $limit=0)
{ // A simple wrapper to prepare, select and return records
global $receipt, $sql_request;
if($limit>0)
{ $conditions="$conditions LIMIT $limit"; }
$sql="SELECT $selection FROM $table WHERE $conditions";
$sql_request=$sql;
//////////////////////////////////////////////////////////////////////////////
$result=[];
try
{ $stmt=DBExecute($DB, $sql);
if (!($res = $stmt->get_result()))
{ Abort("DBSelectData get_result() failed: (" . $stmt->errno . ") " . $stmt->error ." $sql"); }
//////////////////////////////////////////////////////////////////////////////
for ($row_no = ($res->num_rows - 1); $row_no >= 0; $row_no--) {
$res->data_seek($row_no);
$result[]=$res->fetch_assoc();
}
//////////////////////////////////////////////////////////////////////////////
// Reverse our reverse array to put it into correct order
if(isset($result))
{$result=array_reverse($result);}
$stmt->close();
return $result;
} catch (Exception $e)
{
// Handle the error, something went wrong
error_log($e->getMessage());
return DBState($DB, [ "errno"=>$e->getCode(), "error"=>$e->getMessage() ]);
}
return true;
}
function DBState($DB=false, $stmt=false)
{ // Return state of play, give precedence to prepare/execute errno
//////////////////////////////////////////////////////////////////////////////
global $sql_request;
//////////////////////////////////////////////////////////////////////////////
if($stmt&&$stmt["errno"]>0)
{ return [ "affected_rows"=>0, "insert_id"=>0, "errno"=>$stmt["errno"], "error"=>$stmt["error"], "query"=>"$sql_request", "A"=>mt_rand(2,32767) ]; }
return [ "affected_rows"=>mysqli_affected_rows($DB), "insert_id"=>mysqli_insert_id($DB), "errno"=>$DB->errno, "error"=>$DB->error, "query"=>"$sql_request", "B"=>mt_rand(2,32767) ];
}
function DBConnect($DBHOST, $DBUSER, $DBPASS, $DBINSTANCE)
{ // Connect to the db and return a pointer
// Enable DB exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
// Connect
$DB=new mysqli("$DBHOST", "$DBUSER", "$DBPASS", "$DBINSTANCE");
if($DB->connect_errno)
{
$report["DBHOST"]="$DBHOST";
$report["DBUSER"]="$DBUSER";
if(mb_strlen("$DBPASS")>4&&"$DBPASS"!=="false")
{ $report["DBUSER"]="true"; } else { $report["DBUSER"]="false"; }
$report["DBINSTANCE"]="$DBHOST";
$report["errno"]=$DB->connect_errno;
$report["error"]="Connect error: ".$DB->connect_error;
Abort( json_encode( $report, JSON_PRETTY_PRINT) );
}
// Set char set
mysqli_set_charset($DB, 'utf8mb4');
return $DB;
}
function DBClose($DB)
{ // Disconnect from db
$result=DBState($DB, [ "errno"=>0, "error"=>"" ]);
$DB->close();
return $result;
}
DBSelect($DB, "$TABLE[PRODUCTOPTIONSR]",
"PRODUCTOPTIONSR.contentnamekey, CONTENT.contentname INNER JOIN CONTENT ON PRODUCTOPTIONSR.contentnamekey=CONTENT.contentnamekey",
"businessnamekey='8c9007ab5e9942a80b19887057511d7b1f3c5bbea8672dc03f4fd8291f6c18ab' AND ponamekey='c91bafa8aebfb760547c761110441790f263d3c23721a5034b4d26e97b231668' ORDER BY seq");
Your code is very messy due to all the superfluous error checking, which has led you to your current problem. You are catching the error and then returning an array from DBState which then bubbles up to DBExecute. Thus, somewhere there you have a suppressed error which causes your code to execute get_result on an array. Fix your return types and remove all this error checking.
Here's your code after a slight tyding up:
<?php
/**
* A wrapper to prepare, execute a query and return $stmt
*/
function DBExecute($DB, $sql): mysqli_stmt
{
$stmt = $DB->prepare($sql);
$stmt->execute();
return $stmt;
}
/**
* A simple wrapper to prepare, select and return records
*/
function DBSelect($DB, $table, $selection, $conditions, $limit = 0): array
{
if ($limit > 0) {
$conditions = "$conditions LIMIT $limit";
}
$sql = "SELECT $selection FROM $table WHERE $conditions";
$stmt = DBExecute($DB, $sql);
return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
}
/**
* Connect to the db and return a pointer
*/
function DBConnect($DBHOST, $DBUSER, $DBPASS, $DBINSTANCE): mysqli
{
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$DB = new mysqli("$DBHOST", "$DBUSER", "$DBPASS", "$DBINSTANCE");
$DB->set_charset('utf8mb4');
return $DB;
}
It's far from perfect, but at least now the actual error will show up in your error logs. It's still missing parameter type specifications.
Lesson learned: be very careful with try-catch. Use it only if you are sure that you actually need it.
[language : php]
i have a function that have three mysql prepare statements..
when call the function from Api while the function is already processing .. i want to wait that call and resume after the processing finish ...
actually my problem is ... in my function
my first mysql prepare statement select a value from database and bind that result..
the second prepare statement use that result ..
but another call select value from database without wait for the second prepare statement execute from first call...
//function sample...
public function saveSales($query1,$query2,$query3){
//query1 execute and return a result from database
//using that result execute query 2
//execute query 3
// i want to run this three querys without interrupt from another call
}
My Actual Code :
[index.php : slimframework(Api)]
$app->post('/savesalesnew', function(Request $request, Response $response){
$request_data = $request->getParsedBody();
$sm= $request_data['sm'];
$st= $request_data['st'];
$trans = $request_data['trans'];
$user= $request_data['user'];
$pass = $request_data['pass'];
$maxfind = $request_data['maxfind'];
$db = new DbOperations;
$queryPostResult = $db->saveSales($sm,$st,$trans,$user,$pass,$maxfind);
$response_data=$queryPostResult;
$response->write(json_encode($response_data));
return $response
->withHeader('Content-type', 'application/json')
->withStatus(200);
});
[Db operations.php]
public function saveSales($sm,$st,$trans,$user,$pass,$maxfind){
$stmt = $this->con->prepare("SELECT emp_pass FROM emp WHERE emp_name ='$user'");
$stmt->execute();
$stmt->bind_result($password);
$stmt->fetch();
if(strcmp($pass, $password) !== 0) {
return false;
}
$stmt->close();
$mysqli = new mysqli(//connection parameters);
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$mysqli->autocommit(FALSE);
$stmt1 = $this->con->prepare("$maxfind");
$stmt1->execute();
$stmt1->bind_result($maxInvoice);
$stmt1->fetch();
$stmt1->close();
$sm = str_replace("#%#####23###3", $maxInvoice, $sm);
$st = str_replace("#%#####23###3", $maxInvoice, $st);
$trans = str_replace("#%#####23###3", $maxInvoice, $trans);
$mysqli->query("$sm");
$mysqli->query("$st");
$mysqli->query("$trans");
$mysqli->commit();
$mysqli->close();
return true;
}
//-----------------------------
if you have long process on server, you need a column flag in database if data ready or not. set "0" if data not ready "1" in progress "2" ready.
I am trying to build database class using PDO this my first time using pdo so while i am building i am stuck in this problem i was able create and connect to database using class but problem is when i am trying to execute and fetch returned data error says
Call to a member function fetch() on boolean
and yet i can do this fetching inside the class this problem arise only when i am trying to fetch returned data and i have echoed the returned data it is returning 1
This is function that's trying to return (did not use parameters just using dummy)
public function init($query,$param =[]){
if(!$this->bConnected) { $this->Connect(); }
try{
$stmt = $this->pdo->prepare('SELECT * FROM business');
$stmt->execute();
return $stmt->execute();
}catch(Exception $e){
echo $e->getMessage();
}
}
Calling to class object name is $myobj
$stmt = $myobj->init('SELECT * FROM business',$value);
while($rows = $stmt->fetch(PDO::FETCH_ASSOC)){
echo( $rows['bs_name'] ." |" .$rows['bs_id']. "<br>");
}
This is same code only difference is this is inside the class.working without any errors
public function init($query,$param =[]){
if(!$this->bConnected) { $this->Connect(); }
try{
$stmt = $this->pdo->prepare('SELECT * FROM business');
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
while($rows = $stmt->fetch(PDO::FETCH_ASSOC)){
echo( $rows['bs_name'] ." |" .$rows['bs_id']. "<br>");
}
}catch(Exception $e){
echo $e->getMessage();
}
}
Your method returns the result of $stmt->execute() (a boolean indicating success/failure of the statement execution, not the query results).
$stmt = $this->pdo->prepare('SELECT * FROM business');
return $stmt->execute();
Instead, for the method to work the way you're using it, you need to execute the statement and then return the statement itself, not the result of execute().
$stmt = $this->pdo->prepare('SELECT * FROM business');
$stmt->execute();
return $stmt;
An example of one of my queries...
public function db_query_select($query, $params, $param_types){
$dbc = $this->dbConnect();
if($stmt = $dbc->prepare($query)){
//prepared.
//move the types to the front of the param array
array_unshift($params, $param_types);
//call the bind param function with the parameters passed in by reference
//bind_param only allows by reference.
call_user_func_array(array($stmt, "bind_param"), $this->paramsToRefs($params));
//binded.
//attempt to execute the sql statement.
if ($stmt->execute()){
$result = $stmt->get_result();
$stmt->close();
$dbc->close();
return $result;
}
}
//must have failed...
return NULL;
}
how can I change stmt get_result(); to something that is accepted by shared servers/hosts without the native driver... mysqlnd.
Anyone know? without changing all of my functions that use this database function.
Thanks.
UPDATED:::: Thanks to #your common sense, See Answer.
I believe this is what I was after. Hope it helps anyone that was having the same problem as myself. PDO vs MySQLi, seems simpler... no user call func or anything like that.
DB HANDLER:
private function dbConnect(){
$config = parse_ini_file($_SERVER['DOCUMENT_ROOT'].'/NTConfig.ini');
try {
$dbc = new PDO('mysql:host='.$config['DB_HOST'].';dbname='.$config['DB_DATABASE'].'', $config['DB_USER'], $config['DB_PASSWORD']);
$dbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
exit;
}
return $dbc;
}
public function db_query_select($query, $params){
$dbc = $this->dbConnect();
if($stmt = $dbc->prepare($query)){
//prepared.
//attempt to execute the sql statement.
if ($stmt->execute($params)){
$result = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($result);
//$stmt->close();
//$dbc->close();
return $result;
}
}
//must have failed...
return NULL;
}
Outside the DBHANDLER
$query = "SELECT error_desc FROM nt_errors WHERE error_code = :ERROR_CODE LIMIT 1";
//array: holds parameters for the query.
$params = array(
':ERROR_CODE' => $code
);
$result = $db->db_query_select($query, $params);
if ($result == NULL){
$errorText = 'ERROR: Failed to retrieve error';
}
else{
//var_dump($result);
$errorText = $result['error_desc'];
PDO is not only much more user friendly than mysqli but also doesn't have any of such a nasty drawbacks. So I strongly suggest to use PDO instead of mysqli.
With DO, the function you're after should be as simple as this
function run($sql, $args = NULL)
{
$pdo = ...;//your means of getting the connection variable
$stmt = $pdo->prepare($sql);
$stmt->execute($args);
return $stmt;
}
After gettin the function's result, you can chain a fetch method to its call, fetchColumn() in your case.
Given your code is mostly procedural, let me suggest you a very simple PDO wrapper I wrote. So the full code would be:
$sql = "SELECT error_desc FROM nt_errors WHERE error_code = ?";
$errorText = DB::run($sql,[$code])->fetchColumn();
if (!$errorText){
$errorText = 'ERROR: Failed to retrieve error';
}
Here DB class is a better replacement of your dbConnect() function, and run() method is a replacement for db_query_select() that actually can be used for any query type, including insert, update or anything.
I am using bind parameter mysqli function to execute the queries in php . But i want to print last executed query everytime.
public function __construct(){
$this->dbcon = new mysqli('localhost', '*****', '*****', 'db1');
}
public function get_oderlist($email){
$emailid = $this->dbcon->real_escape_string($email);
$stmt =$this->dbcon->prepare("SELECT order_id,email,phone FROM order_historynew where email=? GROUP BY order_id ORDER BY id DESC");
$stmt->bind_param('s',$emailid);
$stmt->execute();
$stmt -> bind_result($order_id,$email,$phone);
while ($stmt->fetch()) {
$Oderlist[]=array('Order_id'=>$order_id,'Useremail'=>$email,'Phone'=>$phone);
}
if($Oderlist){
return $Oderlist;
}else{
return false;
}
}