I am trying the following code to get results from query and display it in the tes.php page.
db.inc.php
<?php
function db_connect()
{
$handle=new mysqli('localhost','rekandoa','rekandoa','rekandoa');
if (!$handle)
{
return false;
}
return $handle;
}
function get_member()
{
$handle=db_connect();
$sql="Select email,nama,alamat,kota,propinsi from users where email=?";
$stmt=$handle->prepare($sql);
$mail='yonghan79#gmail.com';
$stmt->bind_param("s",$mail);
$stmt->execute();
$stmt->bind_result($email,$nama,$alamat,$kota,$propinsi);
$result=$stmt->fetch();
return $result;
}
?>
tes.php
<?php
error_reporting(E_ALL & ~E_NOTICE);
include('db.inc.php');
$w=get_member();
echo $w['member_id'];
echo '<br>';
echo $w['email'];
echo '<br>';
echo $w['status'];
echo '<br>';
?>
I got no error message but the results are not shown, it is just a blank page.
What did I do wrong?
$stmt->bind_result($email,$nama,$alamat,$kota,$propinsi);
The above line will make sure that the results are stored in the variables that you provide. The fetch() function returns TRUE or FALSE - whether the query was successfull, not the actual result. You would need something like
return array(
'email' => $email,
'nama' => $nama,
'alamat' => $alamat,
'kota' => $kota,
'propinsi' => $propinsi);
fetch() itself doesnt return an array it returns a boolean indicating wheter it got a row.
thus you can do:
while($stmt->fetch()) {
//$email,$nama,$alamat,$kota,$propinsi are now filled
}
binding values into an array dynamically (unlike soulmerge's solution) takes a little more craft. I created a Database class that does just that. It acts as a wrapper arround mysqli prepared statements to return results as objects where the select columns act as properties on the object. If you take out the cast to object in the class it will return arrays as you want.
Related
When I dump the array just before the return statement all seems good.
However, when I dump the result it seems empty.
Should be more clear with the code included. I call GetRow from DatabaseHandler, I can see there is an array when I make a dump before the return. (see the var_dump)
public static function GetRow($sqlQuery, $params = null,
$fetchStyle = PDO::FETCH_ASSOC)
{
// Initialize the return value to null
$result = null;
// Try to execute an SQL query or a stored procedure
try
{
// Get the database handler
$database_handler = self::GetHandler();
// Prepare the query for execution
$statement_handler = $database_handler->prepare($sqlQuery);
// Execute the query
$statement_handler->execute($params);
// Fetch result
$result = $statement_handler->fetch($fetchStyle);
}
// Trigger an error if an exception was thrown when executing the SQL query
catch(PDOException $e)
{
// Close the database handler and trigger an error
self::Close();
trigger_error($e->getMessage(), E_USER_ERROR);
}
// Return the query results
exit(var_dump($result)); // SHOWS A PROPER ARRAY
return $result;
}
In the other function which calls it, there is nothing to be seen (false):
// Gets the details of a specific order
public static function GetOrderInfo($orderId)
{
// Build the SQL query
$sql = 'CALL orders_get_order_info(:order_id)';
// Build the parameters array
$params = array (':order_id' => $orderId);
// Execute the query and return the results
$result = DatabaseHandler::GetRow($sql, $params);
exit(var_dump($result)); // SHOWS FALSE
return $result
}
Don't call exit. There's nothing special about arrays in PHP in terms of arguments/return values - the problem is that you're terminating with the exit() call.
From the docs http://php.net/manual/en/function.exit.php:
Terminates execution of the script
In other words, the return statement is unreacheable. So your code never returns because the process exits before it.
While PDO returned an Array, it was unusable for functions like foreach, while, or json_encode (invalid argument).
The solutions was to use MySQLi, it returned exactly the same Array, only this time it was usable for functions like foreach, while, or json_encode.
What is the problem in this function?
function journeygetLeadertalks($link, $journeyid)
{
$thingResult = $link->prepare("SELECT `leadertalks` FROM `journey` WHERE journeyid=:journeyid");
$thingResult->execute([
"journeyid" => $journeyid
]);
if($thingResult->fetchObject()->leadertalks == "NULL")
return "imgs/noimg.png";
else
return $thingResult->fetchObject()->leadertalks;
}
Database picture:
This function works every time exepct when im using it for leadertalks and leadertalksImage, what can I do?
The problem is that you're calling fetchObject() twice. You're calling it once in the if, and then if the value doesn't match, you're calling it again in the else. But your query only returns one row, so the second fetchObject() returns false, and that's not an object. You need to save the result in a variable.
Also, if the query doesn't match anything at all, the initial fetchObject() will return false, so you should check for that as well.
$row = $thingResult->fetchObject();
if ($row && $row->leadertalks == "NULL") {
return "imgs/noimg.png";
} else {
return $row->leadertalks;
}
Below is some poorly written and heavily misunderstood PHP code with no error checking. To be honest, I'm struggling a little getting my head around the maze of PHP->MySQLi functions! Could someone please provide an example of how one would use prepared statements to collect results in an associative array whilst also getting a row count from $stmt? The code below is what I'm playing around with. I think the bit that's throwing me off is using $stmt values after store_result and then trying to collect an assoc array, and I'm not too sure why...
$mysqli = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['db']);
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$result = $stmt->execute();
$stmt->store_result();
if ($stmt->num_rows >= "1") {
while($data = $result->fetch_assoc()){
//Loop through results here $data[]
}
}else{
echo "0 records found";
}
I feel a little cheeky just asking for code, but its a working demonstration of my circumstances that I feel I need to finally understand what's actually going on. Thanks a million!
I searched for a long time but never found documentation needed to respond correctly, but I did my research.
$stmt->get_result() replace $stmt->store_result() for this purpose.
So, If we see
$stmt_result = $stmt->get_result();
var_dump($stmt_result);
we get
object(mysqli_result)[3]
public 'current_field' => int 0
public 'field_count' => int 10
public 'lengths' => null
public 'num_rows' => int 8 #That we need!
public 'type' => int 0
Therefore I propose the following generic solution. (I include the bug report I use)
#Prepare stmt or reports errors
($stmt = $mysqli->prepare($query)) or trigger_error($mysqli->error, E_USER_ERROR);
#Execute stmt or reports errors
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
#Save data or reports errors
($stmt_result = $stmt->get_result()) or trigger_error($stmt->error, E_USER_ERROR);
#Check if are rows in query
if ($stmt_result->num_rows>0) {
# Save in $row_data[] all columns of query
while($row_data = $stmt_result->fetch_assoc()) {
# Action to do
echo $row_data['my_db_column_name_or_ALIAS'];
}
} else {
# No data actions
echo 'No data here :(';
}
$stmt->close();
$result = $stmt->execute(); /* function returns a bool value */
reference : http://php.net/manual/en/mysqli-stmt.execute.php
so its just sufficient to write $stmt->execute(); for the query execution.
The basic idea is to follow the following sequence :
1. make a connection. (now while using sqli or PDO method you make connection and connect with database in a single step)
2. prepare the query template
3. bind the the parameters with the variable
4. (set the values for the variable if not set or if you wish to change the values) and then Execute your query.
5. Now fetch your data and do your work.
6. Close the connection.
/*STEP 1*/
$mysqli = mysqli_connect($servername,$usrname,$pswd,$dbname);
/*STEP 2*/
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
/*Prepares the SQL query, and returns a statement handle to be used for further operations on the statement.*/
//mysqli_prepare() returns a statement object(of class mysqli_stmt) or FALSE if an error occurred.
/* STEP 3*/
$stmt->bind_param('i', $core['id']);//Binds variables to a prepared statement as parameters
/* STEP 4*/
$result = $stmt->execute();//Executes a prepared Query
/* IF you wish to count the no. of rows only then you will require the following 2 lines */
$stmt->store_result();//Transfers a result set from a prepared statement
$count=$stmt->num_rows;
/*STEP 5*/
//The best way is to bind result, its easy and sleek
while($data = $stmt->fetch()) //use fetch() fetch_assoc() is not a member of mysqli_stmt class
{ //DO what you wish
//$data is an array, one can access the contents like $data['attributeName']
}
One must call mysqli_stmt_store_result() for (SELECT, SHOW, DESCRIBE, EXPLAIN), if one wants to buffer the complete result set by the client, so that the subsequent mysqli_stmt_fetch() call returns buffered data.
It is unnecessary to call mysqli_stmt_store_result() for other queries, but if you do, it will not harm or cause any notable performance in all cases.
--reference: php.net/manual/en/mysqli-stmt.store-result.php
and http://www.w3schools.com/php/php_mysql_prepared_statements.asp
One must look up the above reference who are facing issue regarding this,
My answer may not be perfect, people are welcome to improve my answer...
If you would like to collect mysqli results into an associative array in PHP you can use fetch_all() method. Of course before you try to fetch the rows, you need to get the result with get_result(). execute() does not return any useful values.
For example:
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli($config['host'], $config['user'], $config['pass'], $config['db']);
$mysqli->set_charset('utf8mb4'); // Don't forget to set the charset!
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$stmt->execute(); // This doesn't return any useful value
$result = $stmt->get_result();
$data = $result->fetch_all(MYSQLI_ASSOC);
if ($data) {
foreach ($data as $row) {
//Loop through results here
}
} else {
echo "0 records found";
}
I am not sure why would you need num_rows, you can always use the array itself to check if there are any rows. An empty array is false-ish in PHP.
Your problem here is that to do a fetch->assoc(), you need to get first a result set from a prepared statement using:
http://php.net/manual/en/mysqli-stmt.get-result.php
And guess what: this function only works if you are using MySQL native driver, or "mysqlnd". If you are not using it, you'll get the "Fatal error" message.
You can try this using the mysqli_stmt function get_result() which you can use to fetch an associated array. Note get_result returns an object of type mysqli_result.
$stmt->execute();
$result = $stmt->get_result(); //$result is of type mysqli_result
$num_rows = $result->num_rows; //count number of rows in the result
// the '=' in the if statement is intentional, it will return true on success or false if it fails.
if ($result_array = $result->fetch_assoc(MYSQLI_ASSOC)) {
//loop through the result_array fetching rows.
// $ rows is an array populated with all the rows with an associative array with column names as the key
for($j=0;$j<$num_rows;$j++)
$rows[$j]=$result->fetch_row();
var_dump($rows);
}
else{
echo 'Failed to retrieve rows';
}
I'm new to the world of OOP and PDO and just need a bit of a hand when returning data in one function and wanting to use that inside another function.
Below is my function to get all gecko data from my database, at the moment i have it printing out the array so i know it's working.
function getGecko:
public function getGecko($geckoName){
$dbh = $this->dbh;
try {
if (!$geckoName) {
throw new Exception("No gecko name set!");
}
$stmt = $dbh->query("SELECT * FROM geckos WHERE gecko_name = '$geckoName'");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$row_count = $stmt->rowCount();
$row = $stmt->fetch();
if($row_count > 0){
print_r($row);
return true;
} else {
echo 'No information found for '.$geckoName.'!';
return false;
}
}
catch (Exception $e) {
echo $e->getMessage();
}
}
which outputs as - Array ( [gecko_id] => 1 [gecko_name] => Zilly [gecko_aquisition_date] => 0000-00-00 [gecko_type] => Normal [gecko_gender] => Male [gecko_traits] => [gecko_bio] => Hench bastard [gecko_health_check] => All good! [gecko_bred] => 0 [gecko_hatchling] => 0 [gecko_clutch] => [gecko_photo] => ) - no problem.
But i want to use that data inside a function called getMorph to utilise [gecko_type] => Normal. I have tried things like:
public function getMorph($geckoName){
$this->getGecko($geckoName);
echo $row['gecko_type'];
}
But it returns nothing at all. I am quite used to php in the procedural sense, i'm just trying to better myself and my code and wanted to get stuck into OOP. I do apologise if this is considered a 'noob' question but as i say, i am trying to learn.
Thank you for your time :)
The problem with your first function is that you're returning a boolean value. No actual data is returned. Also, in the getMorph() function, you're trying to use the $row variable. This won't work as the $row variable only exists inside the local scope of the function getGecko(). This would actually cause PHP to print an error message. Had you enabled error reporting, you'd have found this out.
To fix the issue, you can modify your first function to return the array:
if($row_count > 0){
// print_r($row);
return $row;
} else {
echo 'No information found for '.$geckoName.'!';
return false;
}
Then, in your second function, you can access the array like so:
public function getMorph($geckoName){
// $morph now contains the entire array
// returned by the other function
$row = $this->getGecko($geckoName);
// output the array contents
echo '<pre>' . print_r($row, TRUE), '</pre>';
// return the specific gecko_type value
return $row['gecko_type'];
}
I suggest you read up on variable scope. It's going to be very useful. Also, completely unrelated the issue above, you're directly inserting the user input in your SQL query. Don't do that! Use parameterized queries instead - that way, you'll be able to avoid SQL injection attacks.
The following questions has more details on the subject:
How can I prevent SQL injection in PHP?
How does PHP PDO's prepared statements prevent sql injection?
Your function getGecko returns only a Boolean and $row is only a local variable in that method. So you can either change the return value to return the actual data or you can create a private variable in your PHP Class.
For changing the return type, you could in getGecko change that return to something like this:
if($row_count > 0){
// ...
return $row;
}
And then in your getMorph function do something like:
public function getMorph($geckoName){
$row = $this->getGecko($geckoName);
echo $row['gecko_type'];
}
I'm using a factory(class) to present forms from a target database table - as defined at class instance. Then on submit, create a new instance of the class which then insert a new record in to the database. $_POST key names match the table column names.
My issue is dynamically assigning bind parameters when the variables are determined at class instance. I'm getting the following, whether I use Reflections method or inline.
Warning: mysqli_stmt::bind_param() [mysqli-stmt.bind-param]: Number of elements in type definition string doesn't match number of bind variables
The following method is called in the sub class after the post array has been contructed and assigned to the class property $array.
private function addrecord($array,$tbl,$_conn){
//define field name array for query statement
foreach ($array as $key=>$value){
$keyarr[]=$key;
}
//BUILD THE QUERY STATEMENT
$query = "INSERT INTO $tbl SET ";
foreach ($keyarr as $key){
$query .= ($key."=?, "); //clone and add next element
}
$query = rtrim($query,", "); //remove EOL whitespace and comma
//done
/*
//Hard code bind parameters works as expected
if (self::$_conn = new mysqli(DB_HOST,DB_UNAME,DB_UPWORD,DB_NAME)){
$stmt=self::$_conn->prepare($query);
$stmt->bind_param("sssss",$array['user_id'],$array['user_name'],$array['user_email'],$array['user_date'],$array['user_active']);
$stmt->execute();
$insertid=$stmt->insert_id;
$stmt->close();
echo "The record was created with id ".$insertid;
}
*/
//Tried re assigning post array as reference
//same error as just passing $array
//$array = $this->refValues($array);
//Binding params using Reflections, same error
self::$_conn = new mysqli(DB_HOST,DB_UNAME,DB_UPWORD,DB_NAME);
$stmt = self::$_conn->prepare($query);
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($stmt,$array);
$stmt->execute();
$stmt->close();
self::$_conn->close();
}
//Pass By Reference required for PHP 5.3+, dev server 5.3.17
function refValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0){
$refar = array();
foreach($arr as $key => $value)
$refar[$key] = &$arr[$key];
return $refar;
}
return $arr;
}
Thanks in advance and much appreciated.
As you can see, mysqli is practically unusable with prepared statements.
So, I'd suggest you to either use PDO or, better, some intelligent library that can make safe query without prepared statments.
With such a library your function will be written in one line
private function addrecord($array,$tbl){
$this->conn->query("INSERT INTO ?n SET ?u", $tbl, $array);
}
please note that if $array is coming from the untrusted source, you have to filter it's content out first.
Per Common Sense, changed process to PDO. Works as expected. Should have done it sooner. Only issue remaining is UI feedback. Would like to return an insert id, however MySQL doesnt return a last insert id for PDO. And again, the class doesnt know the tables structure in advance so hard coding in not an option. Need a workaround. Any thoughts? Heres the new insert process using PDO.
try{
self::$_conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.'', DB_UNAME, DB_UPWORD);
$stmt = self::$_conn->prepare($query);
$arcount=count($array); //set number of bindParam loops
foreach($array as $key=>$value){
$stmtarr[]=$value; //convert assoc to numerated array
}
//re index array so increment will match up with placeholder position
$stmtarr = array_combine(range(1, count($stmtarr)), array_values($stmtarr));
for($i=1;$i<=$arcount;$i++){ //bind variable, one for each placeholder,
$stmt->bindParam($i,$stmtarr[$i]);
}
$stmt->execute();
} catch (PDOException $e){
print "Error: ".$e->getMessage()."<br>";
die();
}
Assume everything else is the same as above.