I'm new to mysqli, I wrote a function as below.
1 - I couldn't find a way for SELECT * query and having bind_result to assign each column value to the same name variable. (e.g. name column value of #row stores to $name)
I think bind_result() has no function on a SELECT * query?
2 - So I tried another option, to fetch all rows and assign them to appropriate variable manually through a loop. I think I should use $query->fetch_all() or $query->fetch_assoc() for looping but I encounter with this:
Fatal error: Call to undefined method mysqli_result::fetch_all()
or
Fatal error: Call to undefined method mysqli_result::fetch_assoc()
However I did a phpinfo() and saw mysqlnd was enabled and php version is 5.4.7 (running XAMPP v1.8.1)
And 3- what finally I did is below idea that doesn't work either.
function the_names($name)
{
global $db;
if($query = $db->prepare("SELECT * FROM users where name=?"))
{
$query->bind_param('s', $name);
if($query->execute())
{
$query->store_result();
if($query->num_rows > 1)
{
while($row = $query->fetch())
{
echo $row['name']; // Here is the problem
}
}
else
echo "not valid";
$query->close();
}
}
}
I need a way to store all fetched data as what bind_result() does, or having them in an array for later use, and it's much better to know both. tnx
One word to answer all your questions at once - PDO
It has everything you are trying to get from mysqli (in vain):
function the_names($name)
{
global $db;
$query = $db->prepare("SELECT * FROM users where name=?");
$query->execute(array($name));
return $query->fetchAll();
}
$names = the_names('Joe');
foreach ($names as $row) {
echo $row['name'];
}
Note the proper way of using a function. it should never echo anything, but only return the data for the future use
If your mysqli code doesn't have binding_param() you can just write code like below :
$mysqli = new mysqli("localhost" , "root" , "" , "database_name");
$result = $mysqli->query( "SELECT * FROM users where name=" . $name) ;
while ( $row = $result->fetch_assoc() ) {
echo $row["name"];
}
If you use binding_param() code , you also need to set bind_result()
$db = new mysqli("localhost" , "root" , "" , "database_name");
function the_names($name){
global $db;
/* Prepared statement, stage 1: prepare */
if (!($query = $db->prepare("SELECT * FROM users where name=?"))) { # prepare sql
echo "Prepare failed: (" . $db->errno . ") " . $db->error;
}
/* Prepared statement, stage 2: bind and execute */
if (!$query->bind_param("s", $name)) { # giving param to "?" in prepare sql
echo "Binding parameters failed: (" . $query->errno . ") " . $query->error;
}
if (!$query->execute()) {
echo "Execute failed: (" . $query->errno . ") " . $query->error;
}
$query->store_result(); # store result so we can count it below...
if( $query->num_rows > 0){ # if data more than 0 [ that also mean "if not empty" ]
# Declare the output field of database
$out_id = NULL;
$out_name = NULL;
$out_age = NULL;
if (!$query->bind_result($out_id, $out_name , $out_age)) {
/*
* Blind result should same with your database table !
* Example : my database
* -users
* id ( 11 int )
* name ( 255 string )
* age ( 11 int )
* then the blind_result() code is : bind_result($out_id, $out_name , $out_age)
*/
echo "Binding output parameters failed: (" . $query->errno . ") " . $query->error;
}
while ($query->fetch()) {
# print the out field
printf("id = %s <br /> name = %s <br /> age = %s <br />", $out_id, $out_name , $out_age);
}
}else{
echo "not valid";
}
}
the_names("panji asmara");
Reference :
http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
Related
I am just using MS Access Database. I am trying to show the data of employee in the last of a year from MS Access Database using PDO prepare statement in PHP.
This is the code:
index.php
<?php
require_once "config.php";
date_default_timezone_set("Asia/Jakarta");
echo "<h3>Employee Data</h3><br><br>";
// START PDO SELECT
try {
$sql = "SELECT USERINFO.Name, USERINFO.Gender, CHECKINOUT.*, IIf(CHECKINOUT.Update = '', '[[ empty ]]', CHECKINOUT.Update) AS update_costum FROM CHECKINOUT
LEFT JOIN USERINFO ON CHECKINOUT.USERID = USERINFO.USERID
WHERE CHECKINOUT.CHECKTIME BETWEEN ? AND ?";
$dateFrom1 = "(Date()-360)";
$dateTo1 = "Date()";
//$dateFrom2 = date("d/m/Y H:i:s");
//$dateTo2 = date("d/m/Y H:i:s", strtotime("-1 years"));
$stmt = $link->prepare($sql);
$stmt->bindParam(1, $dateFrom1 );
$stmt->bindParam(2, $dateTo1 );
$stmt->execute(); // return -1 ?
echo $stmt->rowCount() . "<br><br>";
while ($ds_emp = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "User ID: " . $ds_emp["USERID"] . " || ";
echo "Nama : " . $ds_emp["Name"] . " " . $ds_emp["Gender"] . " || ";
echo "CHECKTIME : " . $ds_emp["CHECKTIME"] . " || ";
echo "Update : " . $ds_emp["update_costum"];
echo "<br>";
}
} catch (PDOException $e) {
echo $e->getMessage();
}
After run the code, I get a couple of weird things.
The $stmt->rowCount(); return -1.
The $ds_emp only have a few data, not as expected. If I run the query directly in MS Access, the query return all of the data like what I expected.
The last line in the page show me this error.
SQLSTATE[22018]: Invalid character value for cast specification: -3030 [Microsoft][ODBC Microsoft Access Driver] Data type mismatch in criteria expression. (SQLFetchScroll[-3030] at ext\pdo_odbc\odbc_stmt.c:543)
Did I put wrong parameters or the query?
I think my query syntax is not wrong.
Why does $stmt->rowCount(); return -1?
Why are only few data stored in $ds_data variable?
How can I fix this?
The $link declaration variable is not shown here but to avoid this error it should be like this one
$dbName = "C:\\path\\to\\db.mdb";
$link = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};charset=UTF-8; DBQ=$dbName; Uid=; Pwd=;");
I'm trying to loop through a stored procedure, called via prepared statement, in PHP. Hopefully it's not impossible. Here's my PHP code:
$database = new mysqli($server, $user, $pass, $db);
$stmt = $database->prepare("CALL thisShouldReturnEightResultSets (?)");
$stmt->bind_param("i", $id);
$stmt->execute();
do {
if ($res = $stmt->bind_result($myvar)) {
$stmt->fetch();
echo "*" . $myvar . "<br/>";
} else {
if ($stmt->errno) {
echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
} while ($stmt->next_result());
That should print like so:
* 4
* 16
* 7
etc...
... and then exit once it runs of out result sets. Instead I get:
* 4
Fatal error: Call to undefined method mysqli_stmt::next_result()
At first I tried get_result instead of bind_result, but that errored. Based on this I found that I don't have the mysqlnd driver installed. Iworked around that with bind_result. Now I need a work around for next_result which I'm guessing is part of the mysqlnd driver as well. What are my options here? Tech notes:
PHP Version 5.3.2-1ubuntu4.11
Thanks.
I don't think you can do this with a prepared statement, since you don't have the MYSQLND driver. You'll have to do it the old fashioned way, with escaping.
$id = $database->real_escape_string($id);
if ($database->multi_query("CALL thisShouldReturnEightResultSets ('$id')")) {
do {
if ($result = $database->store_result()) {
while ($row = $result->fetch_row()) {
echo "*" . $row[0] . "<br/>";
}
}
} while ($database->next_result());
}
bindResult does not like multiple results.
Use get_result() then fetch_assoc and store in an array,
Then use a foreach loop to output your results.
$res = $stmt->get_result();
$array[];
while($x = $res->fetch_assoc()){
$array[]=$x;
}
I am trying to get both the results of my query and the row count wihtout having to make two trips the the DB if possible. I am using prepared statements in a procedural way. My code is as follows:
$dbd = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($dbd, "SELECT * FROM Contacts WHERE First_Name = ?" )) {
mysqli_stmt_bind_param($dbd, "s", $val1);
if (!mysqli_stmt_execute($dbd)) {
echo "Execute Error: " . mysqli_error($dbconnection);
} else {
//do nothing
}
} else {
echo "Prep Error: " . mysqli_error($dbconnection);
}
$result = mysqli_stmt_get_result($dbd);
So the above code works just fine and returns my results. What I want to do now is get the row count using this same statement but i don't want to have to write a brand new prepared statement. If I writer a separate prepared statement and use store_results and num_rows I get the row count but that would force me to have to write an entire new block of code and trip to db. I am trying to do something as follows but It throws and error:
$dbd = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($dbd, "SELECT * FROM Contacts WHERE First_Name = ?" )) {
mysqli_stmt_bind_param($dbd, "s", $val1);
if (!mysqli_stmt_execute($dbd)) {
echo "Execute Error: " . mysqli_error($dbconnection);
} else {
//do nothing
}
} else {
echo "Prep Error: " . mysqli_error($dbconnection);
}
$result = mysqli_stmt_get_result($dbd);
mysqli_stmt_store_result($dbd);
$rows = mysqli_stmt_num_rows($dbd);
The throws and error as if i can't run both get results and store results using the same prepared statement. Im simply trying to keep my code compact and reuse as much as possible. If i break the above out into two separat prepared statements it works fine, Im just wondering there is a way to just add a line or two to my existing statement and get the row count. Or do i have to write an entire new block of code with new stmt_init, stmt_prepare, bind_param, execute, etc...
I tried your code (and reformatted it a bit), but I can't get it to work when I use both store_result() and get_result(). I can only use store_result then bind_result().
So the alternative is to fetch all the rows and then count them:
Example:
$sql = "SELECT * FROM Contacts WHERE First_Name = ?";
$stmt = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($stmt, $sql) === false) {
trigger_error("Prep Error: " . mysqli_error($dbconnection));
return 1;
}
if (mysqli_stmt_bind_param($stmt, "s", $val1) === false) {
trigger_error("Bind Error: " . mysqli_stmt_error($stmt));
return 1;
}
if (mysqli_stmt_execute($stmt) === false) {
trigger_error("Execute Error: " . mysqli_stmt_error($stmt));
return 1;
}
$result = mysqli_stmt_get_result($stmt);
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
$num_rows = count($rows);
print "$num_rows rows\n";
foreach ($rows as $row) {
print_r($row);
}
In my opinion, PDO is much easier:
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test", "xxxx", "xxxxxxxx");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Contacts WHERE First_Name = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$val1]);
$num_rows = $stmt->rowCount();
print "$num_rows rows\n";
while ($row = $stmt->fetch()) {
print_r($row);
}
This question already has answers here:
Build SELECT query with dynamic number of LIKE conditions as a mysqli prepared statement
(2 answers)
Closed 3 years ago.
I'm trying to make a function that receive a query (sql) and a parameter (array) but I receive this error:
PHP Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be
a reference, value given
My code is:
function dbRead($query, $param) {
$mysqli = new mysqli(DB::READ_HOST, DB::READ_USER, DB::READ_PASS, DB::NAME);
// Check that connection was successful.
if ($mysqli->connect_error) {
$result = "Connection error";
} else {
// Check that $conn creation succeeded
if ($conn = $mysqli->prepare($query)) {
call_user_func_array(array($conn, 'bind_param'), $param);
$conn->execute();
$result = $conn->get_result();
$result = $result->fetch_array();
$conn->close();
} else {
$result = "Prepare failed";
}
}
$mysqli->close();
return $result;
}
$test = dbRead('SELECT * FROM user WHERE id=? and email=?', array(123,'example#example.com'))
And if my function code is
function dbRead($query, $param) {
$mysqli = new mysqli(DB::READ_HOST, DB::READ_USER, DB::READ_PASS, DB::NAME);
// Check that connection was successful.
if ($mysqli->connect_error) {
$result = "Connection error";
} else {
// Check that $conn creation succeeded
if ($conn = $mysqli->prepare($query)) {
$ref = array();
foreach ($param as $key => $value) {
$ref[$key] = &$param[$key];
}
call_user_func_array(array($conn, 'bind_param'), $ref);
$conn->execute();
$result = $conn->get_result();
$result = $result->fetch_array();
$conn->close();
} else {
$result = "Prepare failed";
}
}
$mysqli->close();
return $result;
}
I receive this error
PHP Warning: mysqli_stmt::bind_param(): Number of elements in type
definition string doesn't match number of bind variables
My PHP version is 5.4.36
I was trying to do something very similar and pieced together the solution from a few different posts on PHP References and bind_param. What's probably not immediately clear from the bind_param examples (or you forgot) is that the first argument is a string of the parameter types, one character per parameter (in your case, likely "is" for int and string), and you already got that the rest of the arguments must be references in your second function definition.
So, creating the arguments array should be something like this instead:
$ref = array("is");
foreach ($param as $value)
$ref[count($ref)] = &$value;
Though there are many ways to do it... and you should probably pass in the argument types along with the query, but MySQL seems to be relaxed when it comes to type exact types. I also prefer to pass the connection around, and support multiple result rows, e.g.:
function doRead($conn, $query, $argTypes, $args){
$success = false;
$execParams = array($argTypes);
foreach($args as $a)
$execParams[count($execParams)] = &$a;
if (!$stmt = $conn->prepare($query)){
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
}else if (!call_user_func_array(array($stmt, "bind_param"), $execParams)){
echo "Param Bind failed, [" . implode(",", $args) . "]:" . $argTypes . " (" . $stmt->errno . ") " . $stmt->error;
} else if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
} else
$success = true;
$ret = array();
if($success){
$res = $stmt->get_result();
while ($row = $res->fetch_array(MYSQLI_ASSOC))
array_push($ret, $row);
}
$stmt->close();
return $ret;
}
I am trying to create a PHP array of random "fruits" from a database.
The database class that I am using:
class Db
{
private static $_instance = null;
private $_pdo;
private function __construct()
{
try {
$this->_pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME .'', DB_USER, DB_PASS);
} catch (PDOException $e) {
die($e->getMessage());
}
}
public static function getInstance()
{
if (!isset(self::$_instance)) {
self::$_instance = new Db();
}
return self::$_instance;
}
public function prepare($sql)
{
return $this->_pdo->prepare($sql);
}
}
The class that is using the database to fetch "fruits" to create an array of a given size of random entries by using 3 seperate queries to calculate and retrieve "x" number of random items form the database.
class FruitBasket
{
private $_fruitArray = array(),
$_inputCode,
$_db;
public function __construct($input = null)
{
$this->_inputCode = $input;
$this->_db = Db::getInstance();
var_dump($this->_db);
}
public function pickFruit($count)
{
$doubleCount = $count * 2;//double the count used in calculation with the random number
$fruitIDs = ''; //the choosen fruits (id's)
$i = 0;
//#1 get total count of fruits table
$sql = "SELECT COUNT(*) FROM `fruits`";
if ($query = $this->_db->prepare($sql)) {
if ($query->execute()) {
$allFruits = $query->fetch(PDO::FETCH_NUM);
} else {
print_r("ERROR QUERY DID NOT EXECUTE #1");
}
} else {
print_r("ERROR CHECK SQL SYNTAX #1");
}
//#2 calculate random number to pull from all of id's
$sql = "SELECT id FROM `fruits` WHERE RAND()* ? < ? ORDER BY RAND() LIMIT 0, ? ";
if ($query = $this->_db->prepare($sql)) {
$query->bindParam(1, $allFruits[0], PDO::PARAM_INT);
$query->bindParam(2, $doubleCount, PDO::PARAM_INT);
$query->bindParam(3, $count, PDO::PARAM_INT);
if ($query->execute()) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
if ($i == 0) {
$fruitIDs .= "'" . $row['id'] . "'";
} else {
$fruitIDs .= ", '" . $row['id'] . "'";
}
$i++;
}
} else {
print_r("ERROR QUERY DID NOT EXECUTE #2");
}
} else {
print_r("ERROR CHECK SQL SYNTAX #2");
}
//#3 get the fruits
$sql="SELECT NAME FROM `fruits` WHERE `id` IN( ? )";
if ($query = $this->_db->prepare($sql)) {
$query->bindParam(1, $fruitIDs, PDO::PARAM_STR);
if ($query->execute()) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$this->_fruitArray[] = $row['name'];
}
} else {
print_r("ERROR QUERY DID NOT EXECUTE #3");
}
} else {
print_r("ERROR CHECK SQL SYNTAX #3");
}
return $this->_fruitArray;
}
}
The table that I am attempting has a bunch of "fruits" in it, an example of how the table is structured:
==================================
| ID | NAME |
==================================
| 01 | Apple |
==================================
I am attempting to test this all out by using the following:
echo "<pre>";
echo "TESTING FRUIT ARRAY:</br></br>";
$basket = new FruitBasket();
echo"</br></br> PRINT_R: </br></br>";
print_r($basket->pickFruit(10));
echo "</br></br> VARDUMP: </br></br>";
var_dump($basket->pickFruit(10));
The sql query prepares and executes properly, I can do a vardump of the prepares and the binds and they return TRUE. Nothing is returned on the last query however.
In the first query that executes Doing a print statement of $allFruits shows the correct total count from the table.
The second query seems to be working properly,the string $fruitIDs, gets random id's from the table, I can echo this out and confirm that indeed the correct number of ID's are returned.
The problem occurs (I think) with the third query:
Nothing is returned form this query. The prepare statement returns true on a var dump as does the execute, however there is no results!
If I manually take the ID's that are output from query#2 and run it myself in mysql, the correct "fruit" names are returned.
Am I binding the variables incorrectly? I read the pages from the PHP manual but clearly I am doing something wrong.
Please help! :)
Thanks to the links and input provided by Your common sense, using the following:
Reference - frequently asked questions about PDO
and
Can I bind an array to an IN() condition?
I was able to resolve this by changing my query as follows:
//#2 calculate random number to pull from all of id's
$sql = "SELECT id FROM `fruits` WHERE RAND()* ? < ? ORDER BY RAND() LIMIT 0, ? ";
if ($query = $this->_db->prepare($sql)) {
$query->bindParam(1, $allFruits[0], PDO::PARAM_INT);
$query->bindParam(2, $doubleCount, PDO::PARAM_INT);
$query->bindParam(3, $count, PDO::PARAM_INT);
if ($query->execute()) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$fruitIDs[] = $row['id'];
}
} else {
print_r("ERROR QUERY DID NOT EXECUTE #2"); }
} else {
print_r("ERROR CHECK SQL SYNTAX #2");
}
//#3 get the fruits
$inQuery = implode(',', array_fill(0, count($fruitIDs), '?'));
$sql="SELECT NAME FROM `fruits` WHERE `id` IN($inQuery)";
if ($query = $this->_db->prepare($sql)) {
if ($query->execute($fruitIDs)) {
while ($row = $query->fetch(PDO::FETCH_NUM)) {
$this->_fruitArray[] = $row[0];
}
} else {
print_r("ERROR QUERY DID NOT EXECUTE #3");
}
} else {
print_r("ERROR CHECK SQL SYNTAX #3");
}
return $this->_fruitArray;
}
I do not fully understand the security benefits or ramifications of binding the parameters or simply including them in the actual execute() but for now the query is performing as intended, so thank you for the input!