Fetch multiple rows in mysql single query in php with different id - php

I have different id's, i am getting the values of these id from users
$id=array();
$id[0]=$_GET["id0"];
$id[1]=$_GET["id1"];
$id[2]=$_GET["id2"];
now to fetch data from database i am using following query:
for($j=0;$j<count($id);$j++)
{
$res=mysql_query("SELECT * FROM mutable WHERE id='$id[$j]'")
while($row=mysql_fetch_array($res))
{
$row[]=array("email"=>$row[2],"name"=>$row[3],"address"=>$row[5]);
echo JSON_encode($row);
}
}
now i am getting proper result from this query using for loop but the result is not in proper JSON format, is there any way to do it more efficentyly and getting proper result in JSON array and JSON object format

Place json_encode() outside of your loops.
Let's modernize and refine things...
*Unfortunately prepared statements that use an IN clause suffer from convolution. pdo does not suffer in the same fashion.
Code: (untested)
if(isset($_GET['id0'],$_GET['id1'],$_GET['id2'])){
$params=[$_GET['id0'],$_GET['id1'],$_GET['id2']]; // array of ids (validation/filtering can be done here)
$count=count($params); // number of ids
$csph=implode(',',array_fill(0,$count,'?')); // comma-separated placeholders
$query="SELECT * FROM mutable WHERE id IN ($csph)";
$stmt=$mysqli->prepare($query); // for security reasons
array_unshift($params,str_repeat('s',$count)); // prepend the type values string
$ref=[]; // add references
foreach($params as $i=>$v){
$ref[$i]=&$params[$i]; // pass by reference as required/advised by the manual
}
call_user_func_array([$stmt,'bind_param'],$ref);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array(MYSQLI_NUM))
$rows=["email"=>$row[2],"name"=>$row[3],"address"=>$row[5]];
}
$stmt->close();
echo json_encode($rows);
}

Three things:
Always, always, always used prepared statements and bound parameters when dealing with untrusted (i.e., $_GET) input. Just do it.
As regards your problem with JSON, you only need to run json_encode once:
$results = [];
for($j=0;$j<count($id);$j++) {
...
while($row=mysql_fetch_array($res)) {
results[] = ...
}
}
json_encode( $results );
Use a single SQL statement, since you have a known number of IDs to collect:
$dbh = new PDO($dsn, $user, $password);
$sql = "SELECT * FROM mutable WHERE id IN (?, ?, ?)";
$sth = $dbh->prepare( $sql );
foreach ( $sth->execute( [$_GET['id0'], $_GET['id1'], $_GET['id2']] ) as $row ) {
...
This is more efficient then multiple round trips to the database. For this contrived case it probably doesn't matter, but getting into good habits now will serve you in the long run.

you have used $row wrongly, declare array variable outside of loop like
$json_response = array();
for($j=0;$j<count($id);$j++) {
$res=mysql_query("SELECT * FROM mutable WHERE id='$id[$j]'")
while($row=mysql_fetch_array($res)) {
$json_response[]=array("email"=>$row[2],"name"=>$row[3],"address"=>$row[5]);
echo json_encode($json_response); // not good to echo here
}
}
// echo json_encode($json_response); // ideally echo should be here

Related

PDO can I reuse the same Statement Handle for multiple queries?

I am using PDO to access my data base and am looping using two while loops with fetch at the same time, seen below:
$DBH = new PDO('mysql:host=localhost;dbname=database;charset=utf8',$dblogin,$dbpass);
$sql = 'SELECT * FROM table';
$STH = $DBH->prepare($sql);
$STH->execute();
while ($bm_table = $STH->fetch(PDO::FETCH_ASSOC))
{
// SQL Query
$sql1 = 'QUERY HERE';
$STH1 = $DBH->prepare($sql1);
$STH1->execute();
// Loops through using different handle, but what if I used STH again?
while ($row = $STH1->fetch(PDO::FETCH_ASSOC))
{
SomeFunction($bm_table,$row);
}
}
As you can see above I am using a different statement handle ($STH, $STH1 etc.) Is this necessary? Or can I use just one statement handle for everything. The reason I have used multiple handles is as the $bm_table value that uses $STH, will still be in use while I am fetching $row wouldn't that change the value of $bm_table or stop the fetch from working? How does the handles with PDO work? Especially when in this case I have two simultaneous fetch loops running at the same time using the same PDO connection.
So the main thing I am looking for here is if I have two statements that are running simultaneously is it important that I use different handles when I continue to use the same connection?
$STH and STH1 are not statement handles, they're just PHP variables. You can reassign a variable if you no longer need its old value. But in the case of this code, you still need the old value.
If you assign $STH inside the outer loop to the handle returned by the second prepare() call, then when it gets back to the top of the loop and re-executes the $STH->fetch() test, it will try to fetch from the second query, not the first one. This will immediately end the outer loop because all those rows have been read.
You can reuse a statement handle for repetitions of the same query. This is very useful when the query has parameters:
$stmt = $DBH->prepare("SELECT * FROM tablename WHERE id = :id");
$stmt->bindParam(':id', $id);
foreach ($id_array as $id) {
$stmt->execute();
$row = $stmt->fetch();
// do stuff with $row
}
If I understand you correctly what you want is dynamic query?... just put a parameter on your method then...
something like this. call it as much as you want with difference parameters though.
Class SampleClass{
public function GetAll($tablename)
{
$sth = $this->prepare("SELECT * FROM $tablename");
$sth->execute();
return $sth->fetchAll();
}
}

SQL query in Foreach loop using array variable

UPDATE:
WORKING CODE, Thanks jon for the push in the right direction.
<?php
$stmt2 = $conn->prepare("SELECT * FROM userItems WHERE id=:id");
foreach ($moodItems as $id2)
{
// bind the parameters
$stmt2->bindValue(":id", $id2);
if ($stmt2->execute()) {
if($result = $stmt2->fetch(PDO::FETCH_ASSOC)) {
// initialise an array for the results
$itemName2 = $result['itemName'];
$name2 = $result['userId'];
echo $itemName2."<br>";
echo $name2."<br>";
}
}
}
?>
I am having trouble using a SQL query in a foreach loop. I am trying to use the value from the first query(which is an array) and use it in the second query.
The first query works correctly to give me the proper value(array).But for some reason when I try to use the array in the foreach it does not work properly, it does not show any errors...it just does not fetch any data from the database.
IE/ echo $itemName2; <----does not get any info from database
Any help would be great. Thanks.
here is the code I am working with:
<?php
$attrs = array(PDO::ATTR_PERSISTENT => true);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare the statement.
$stmt = $conn->prepare("SELECT * FROM userMoodboard WHERE name=:name");
// bind the parameters
$stmt->bindValue(":name", $loggedInUser->username);
// initialise an array for the results
if ($stmt->execute()) {
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$imageUrl = $row['imageUrl'];
$moodItems = $row['moodItems'];
$moodItems = json_decode($moodItems);
?>
<img src='<?php echo $imageUrl;?>' class="thumbnail"></img>
<?php
$stmt = $conn->prepare("SELECT * FROM userItems WHERE id=:id");
foreach ($moodItems as $id)
{
// bind the parameters
$stmt->bindValue(":id", $id);
// initialise an array for the results
if($stmt->execute()) {
$itemName2 = $row['itemName'];
$name2 = $row['userId'];
echo $itemName2;
echo $name2;
}
}
}
}
?>
There are a couple of things wrong with your code, but we'll start with your second statement.
$stmt = $conn->prepare("SELECT userId FROM userItems WHERE id=:id");
foreach ($moodItems as $id)
{
// bind the parameters
$stmt->bindValue(":id", $id);
// initialise an array for the results
if($stmt->execute()) {
$itemName2 = $row['itemName'];
$name2 = $row['userId'];
echo $itemName2;
echo $name2;
}
}
You are trying to pull out $row['itemName'] and $row['userId'], however, you never SELECT the itemName column in that query. So if you want that information, you'll have to select it first. Aside from that, you execute the query, but you never fetch the row with information.
Those are the basics of why the second portion will not work how you want it to.
Now, for the bigger picture. Most of the block of code you provide is a nested if for your first $stmt->execute() and then within a while($row = ... Which, by itself is fine. However, later within the same block, you prepare another statement, which is perfectly acceptable, but you assign it to the same $stmt variable that you are using for the loop in the first place, which will also cause you problems. You'll want to assign a new variable for your second prepared statement, so you can work with the new data-set. Also, going back to the previous block I posted in, you'll want to fetch it to a variable that is not $row, as that is also a used variable.
UPDATE: As pointed out by Jon, my answer applies to Zend_Db_Adapter and not to PDOStatement (which you are using). My apologies.
The problem probably is that you're doing $stmt->execute() on the second SQL query. execute() does not return results, what you want to do is to fetch(), which does return results.

Initializing variable from PDO query

$q = $db->query(" SELECT username FROM users WHERE userident = '1' ");
echo $q; //error
print_r $q; //prints the query information (SELECT ... etc)
How do I go about getting the specific value of the element I am querying? Say the element under column username and where userident equals '1' contains the value "Patrick"; how do I initialize this string into a variable?
//same query as above
$user = $q;
echo $user; //prints "Patrick"
Sorry if this is something so rudimentary and mundane, but I've never done this outside of a foreach() loop. I'd normally iterate through rows to print specific details. The below works, but the foreach() is unnecessary as far as I understand.
foreach($q as $p) {
$user = $p["username"];
}
echo $print; //this correctly prints "Patrick"
Surely there's a method I missed somewhere?
Using the query method pretty much defeats the purpose of using prepared statements. Plus, I believe for what you're looking for, it isn't quite right.
<?php
if (!isset($_POST['id'])) {
exit;
}
$userId = $_POST['id'];
$db = new PDO(/* Stuff */);
$sql = '
SELECT username
FROM users
WHERE id = :id';
// Get a prepared statement object.
$statement = $db->prepare($sql);
// Bind a parameter to the SQL code.
$statement->bindParam(':id', $userId, PDO::PARAM_INT);
// Actually get the result.
$result = $statement->fetch(PDO::FETCH_ASSOC);
// Close the connection.
$statement->closeCursor();
// Print the result.
print_r($result);
Alternately you can use $statement->fetchAll() to gather more than one result.
Edit: I didn't actually run this code, so you might have to tinker with it to get it working right.

PHP MySQLi prepared statements and fetching subset of columns

I am using MySQLi and PHP to call a stored MySQL routine with prepared statements. It returns a result set with dozens of columns.
$stmt = $dbconnection->prepare("CALL SomebodysDbProcedure(?);");
$stmt->bind_param("s", $idvalue);
$stmt->execute();
$stmt->bind_result($col1, $col2, $col3, ...);
However, I am only interested in a subset of the output columns.
The documentation says bind_result() is required to handle the complete set of returned columns:
Note that all columns must be bound after mysqli_stmt_execute() and
prior to calling mysqli_stmt_fetch().
Do I need to add code also for those columns I'm uninterested in? If so the application will break if the MySQL stored routine result set is expanded in the future, or even columns rearranged. Is there a workaround for this?
I'm assuming that you just don't want to write out all those variables for the bind_result() function. You could use a function like below instead of the bind_result() function. Pass it your $stmt object and you'll get back an array of standard objects with the fields you want.
function getResult($stmt)
{
$valid_fields = array('title', 'date_created'); // enter field names you care about
if (is_a($stmt, 'MySQLi_STMT')) {
$result = array();
$metadata = $stmt->result_metadata();
$fields = $metadata->fetch_fields();
for (; ;)
{
$pointers = array();
$row = new \stdClass();
$pointers[] = $stmt;
foreach ($fields as $field)
{
if (in_array($field->name, $valid_fields)) {
$fieldname = $field->name;
$pointers[] = &$row->$fieldname;
}
}
call_user_func_array('mysqli_stmt_bind_result', $pointers);
if (!$stmt->fetch())
break;
$result[] = $row;
}
$metadata->free();
return $result;
}
return array();
}
The answer of Jonathan Mayhak guided me in the right direction. On PHP bind_result page, nieprzeklinaj provides a function called fetch(). It works; use it like this:
$stmt = $conn->prepare("CALL SomebodysDbProcedure(?);");
$stmt->bind_param("s", $idvalue);
$stmt->execute();
$sw = (array)(fetch($stmt));
$s = $sw[0]; // Get first row
$dateCreated = $s['date_created']; // Get field date_created
Edit: Unfortunately successive calls within the same PHP file don't seem to work with this method.
Try using fetch_fields php method:
array mysqli_fetch_fields ( mysqli_result $result )
http://php.net/manual/en/mysqli-result.fetch-fields.php

A Strategy for using PDO? (Pushing results into an Array)

Here is my somewhat broken strategy
If it is a query with no input ( always the same ), just use query();
$results = $this->database_top->query( $query );
If a single row is returned and there is input, do the prep (not shown here) and use
$results = $pdoStatement->fetch(PDO::FETCH_ASSOC);
If multiple rows are returned and there is input,do the prep (not shown here) and use:
$results = $pdoStatement->fetchAll();
Problem I'm facing is that I need the first method to return an array or array of arrays like the second and third.
Prep looks like this FYI
$this->database_top->quote($query); // quote it
$pdoStatement = $this->database_top->prepare($query); // prepare it
$results = $pdoStatement->execute($parameterArray); // execute it
How can I modify my code so that all 3 methods return arrays or array of arrays?
Iterating over query()
$result_array = $this->DatabaseObject->_pdoQuery( 'multiple', 'tweet_model' );
foreach( $result_array as $array_1d )
{
$array_2d[]=$array_1d;
}
query does not return results, so I'm not sure what you meant on the first example. query returns a PDOStatement. It's basically the same as:
$qry = $db->query("...");
//equiv:
$qry = $db->prepare("...");
$qry->execute();
As vicTROLLA noted, the simplest solution is to just use:
$results = $stmt->fetch(PDO::FETCH_ASSOC);
However, if you need to process the results as you go for some reason, you could always loop over them manually.
$stmt = ...;
$results = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$results[] = $row;
}
//use or return $results
$results will thus always be an array with 0 or more arrays inside of it.
I find it useful to build arrays where the array key is the primary key of the record:
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$results[$row['id']] = $row;
}
Also, I suspect that you've misunderstood the purpose and functionality of quote. It is used for escaping strings that you are going to interpolate into a query, not for magically escaping all values in a query (hence $db->quote($query) makes no sense).
Even worse is that drivers are not required to support quote. (Though it does at least return false if there's no support.)
prepare is massively preferred over quote.
In all of those cases, you can do
$arrayOfAssocArrays = $pdoStatement->fetchAll(PDO::FETCH_ASSOC);

Categories