PDO fetch multiple records from database - php

I am writing a pretty basic piece of code to fetch one or (in most cases) multiple rows from a mysql database.
function getschema($mysqli){
$id = $_SESSION['user_id'];
$query = $mysqli->prepare("SELECT a.naam
FROM schemes AS a, aankoop AS b
WHERE b.aankoop_username_id = :userid && b.aankoop_schema_id = a.id");
$query->bind_param(':userid', $id, PDO::PARAM_INT);
$query->execute();
$result = $query->fetchAll();
echo ($result);
}
I get the user id from the session and pull the data with the query in the prepared statement.
This statement is correct. I tried it in phpmyadmin and it returns the correct values.
Now I want to use this function in my HTML like so...
<?php echo getschema($mysqli); ?>
But my code does not return a thing, it even messes up the layout of my html page where I want to show the code.
I think it probably is something with the fetchAll command. I also tried the PDO::Fetch_ASSOC but that did not work either.
In addition, I cannot see the php errors, even when they are enabled in the php.ini file.

Here's what's going on; you're mixing MySQL APIs/functions and those do not intermix.
Replace the :userid (PDO) bind in b.aankoop_username_id = :userid with a ? placeholder
b.aankoop_username_id = ?
Then this line:
$query->bind_param(':userid', $id, PDO::PARAM_INT);
Replace :userid by $id and remove , PDO::PARAM_INT but adding i
$query->bind_param("i", $id);
Sidenote: Make sure that column is int type. If not, use s instead of i.
Replace the line for fetchAll with the loop as outlined in AbraCadaver's answer.
You can't mix MySQL APIs/function, read the following on Stack:
Can I mix MySQL APIs in PHP?
Read up on mysqli with prepared statements and how it works:
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
Checking for errors would have outlined the errors.
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/function.error-reporting.php

Instead of echo ($result); do return $result; in your function.
Then to use it you have to loop over the array of rows and echo the column that you want:
foreach(getschema($mysqli) as $row) {
echo $row['naam'];
}
Or assign the function return to a variable and loop over that:
$rows = getschema($mysqli);

Related

PHP Fetchall only returning column header

I have a database that I am trying to query to get information to display to my user. I have used
fetch(PDO::FETCH_ASSOC)
before when retrieving a single row or
$row = mysql_fetch_array($result)
with good results. However, it is my understanding that it is better practice to use PDO so that is what I am trying to do.
The problem I am running into is that my results are only showing me the first row of the data I need. In this instance it is displaying the column header over and over and never giving me the data.
$stmt = $conn->prepare("SELECT ? FROM application");
$stmt->bindparam(1, $application_ID);
$stmt->execute();
$results = $stmt->fetchall(PDO::FETCH_ASSOC);
foreach($results as $row){
echo $row['application_ID'];
}
Here are the results
application_IDapplication_IDapplication_IDapplication_ID
It is good that you are aware that MySQL has been oficially deprecated and now we are supposed to used MySQLi or better yet, PDO.
Since you are not accepting any user input, there is no need of using a prepared statement.
Simply do this:
$stmt = $conn->query("SELECT * FROM application");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($results as $row){
echo $row['application_ID'];
//output other rows here
}
As per the php documentation pdo::fetchAll
you have to use fetchAll, instead of fetchall.

PHP PDO Select Query Results

This seems like it should be a very easy task, but I'm not sure it is.
I would like to use PDO to do a SELECT query, and then immediately after find out if there are any results (rows), and if so how many.
I'd like to fetch the result as an object not an array, as I like the $obj->col_name syntax, and it just feels a bit wrong to return an array just to find the above out.
$qryh = $conn->query("SELECT ...");
Then use $qryh to first find out if there are any rows, and if so how many.
Can this be done without falling back to using arrays..?
UPDATE:
I know about rowCount(), but I think it only works on UPDATE, INSERT and DELETE - my question relates to SELECT.
UPDATE 2:
I'm using SQL Server and MS Access, not MySQL, and rocount() does not work.
SOLUTION FOUND
The accepted answer lead to the solution. Here is what I found:
I was setting the PDO::ATTR_CURSOR option to PDO::CURSOR_SCROLL when creating the PDO object (new PDO(...), which returned -1 on a rowCount(). However if I set the cursor within ->prepare(... using an array (array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL)) it works and returns the row count.
http://technet.microsoft.com/en-us/library/ff628154(v=sql.105).aspx
So, the example on the above link works, setting the cursor when you create the PDO object doesn't work. Also note that in the 'remarks' section on the above link, it mentions PDO::CURSOR_SCROLLABLE which doesn't for me (I get Undefined class constant 'CURSOR_SCROLLABLE').
Try this way:
$query = "select * from ...";
$stmt = $conn->prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
print $stmt->rowCount()
Should work
$stmt = $conn->query('SELECT ...');
// number of rows:
$rows = $stmt->rowCount();
// get an array with objects:
$objects = $stmt->fetchAll();
// another way to count the results:
$rows = count($objects);
This is what I do in my database class:
$stmt = $conn->prepare('SELECT ...');
$stmt->execute();
$arrayOfObjects = $stmt->fetchALL(PDO::FETCH_OBJ);
$numberOfRows = count($arrayOfObjects);
print $numberOfRows;
By passing PDO::FETCH_OBJ each object is an stdClass meaning you can use the -> syntax.
I believe this is what you are looking for, and it just uses the PHP count() function instead of mySQL rowCount().
If you want more context, here is the DB class I use in all of my projects: https://gist.github.com/pxlsqre/9f6471220ef187343f54
You're right, PDO::rowCount does not work properly with SELECT
One workaround is to Add the count to your query
$qryh = $conn->query("SELECT COUNT(*) as numRows FROM Table");
$result = $qryh->(PDO::FETCH_OBJ);;
$count = $result->numRows;
$qryh->fetchColumn()
Returns the number of rows selected through a SELECT query

How to use a quoted string variable in a MySqli prepared statement?

Sorry if this seems a really stupid question, but I'm struggling to get to grips with changing from Mysql to Mysqli and prepared statements.
So in mysql, I would have done this:
$q=('SELECT * FROM table WHERE field="'.$variable.'"');
$result = mysql_query($q);
I now know this is not good. So I now have the below:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
$stmt->execute();
Problem is that the query doesn't work. Say the ? is actually "tree". So the query becomes:
'SELECT * FROM table WHERE field=tree LIMIT 1'
If I tried to run that query in say phpmyadmin I get "Unknown column tree in where clause". Obviously if I put quotes around it then it works, hence the original query. So how can I get this to work if I can't use quotes, since then you are looking for the literal question mark?
For reference I am then using this code:
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
As I can't use get_result() which is very annoying. I have PHP version 5.4, and even the mysqlnd driver, but can't enable it as I'm on a VPS and my host says it might affect other sites on that server. Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Any help would be appreciated!
This:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
is not equivalent to this:
SELECT * FROM table WHERE field=tree LIMIT 1
Prepared statement placeholders are not the same as copy and pasting in values. You are binding the value "tree" as a string here, the database will actually understand this. The ? is not simply being replaced by the bound value, the database understands the difference between your query structure with its placeholders and the values you're binding into them. Binding the parameter this way is equivalent to running:
SELECT * FROM table WHERE field='tree' LIMIT 1
Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Mysqli is not intended to be used as is. It is but a building material for the higher level library. When used wisely, it can give you data in one line:
$data = $db->getAll('SELECT * FROM table WHERE field=?s', $variable);
(BTW, the same goes for the old mysql ext as well)

PDO mySql query not executing in for loop the second time up while calling

I have an issue, I'm looping threw a set of values and then creating a PDO mySql query with every loop, now the problem is the first query is executing and returning results, but the second upwards aren't returning results. If I manually execute the queries on the server they return results. This is weird, maybe I'm doing something wrong here. My code below
if($num_results > 0){
for($i=0;$i<$num_results;$i++){
$sql_sub = "SELECT * FROM menu_config WHERE client_id =".$client_id ." AND id =".$data[$i]['root_menu_id'];
$results_s = $pdo->query($sql_sub);
$data_s = $results_s->fetchAll(PDO::FETCH_ASSOC);
$sub_menu_title = "<strong>".$data[$i]['title']."</strong>";
if(empty($data_s[0]['title'])){
$main_menu_title = '<span style="color:#FF0000;font-weight:bold;">No Main Menu Assigned to Sub Menu</span>';
}else{
$main_menu_title = $data_s[0]['title'];
}
$men_title = $data[$i]['title']
}
}
(this may be a little more than you asked for)
You seem to be missing out on some good things that prepared statements do.
First off, you don't usually want to pass the values directly into the query. (sometime's it's necessary, but not here). By doing that, you take out all the good stuff that protects from sql injection. Instead you want to send them as parameters after you've prepared the query.
Secondly, when in a loop, you can save yourself time and resources if you're running the same query over and over by preparing the statement, and then only changing the values you send to to that prepared statement using the PDOStatement::bindParam() function.
Thirdly, fetchAll() does not take a 'fetch_style' of PDO::FETCH_ASSOC. fetch() does. But I think you can get by with the default or none using fetchAll. You'll have to check into that and see what you need. Here are the fetchAll docs
$sql_sub = "SELECT * FROM menu_config WHERE client_id = :client_id AND id = :id ";
$query = $pdo->prepare($sql_sub);
for($i=0;$i<$num_results;$i++){
$query->bindParam(':client_id', $client_id);
$query->bindParam(':id', $data[$i]['root_menu_id']);
$query->execute();
$data_s = $query->fetchAll();
$sub_menu_title = "<strong>".$data[$i]['title']."</strong>";
if(empty($data_s[0]['title'])){
$main_menu_title = '<span style="color:#FF0000;font-weight:bold;">
No Main Menu Assigned to Sub Menu</span>';
}else{
$main_menu_title = $data_s[0]['title'];
}
$men_title = $data[$i]['title'];
}

Why doesn't this prepare statement work in MYSQLI?

I created this code:
$statement = $db->prepare("SELECT * FROM phptech_contact");
$statement->execute();
$result = $statement->result_metadata();
$object = $result->fetch_object();
print_r( $object );
When I run it, it doesn't work. Can anybody tell me why it doesn't work?
I have 20 rows in this table so data should be returned.
From http://ch.php.net/manual/en/mysqli-stmt.result-metadata.php
Note: The result set returned by mysqli_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with mysqli_stmt_fetch().
As long as you don't need this meta data you don't need to call this method.
$statement = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$statement->execute();
$stmt->bind_result($fld1, $fld2);
while ($stmt->fetch()) {
echo "$fld1 and $fld2<br />";
}
But I really dislike the mysqli extension. PDO is much cooler ... ;-)
$db = new PDO('...');
$stmt = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$stmt->execute();
while ($obj = $stmt->fetchObject()) {
// ...
}
or
$objs = stmt->fetchAll(PDO::FETCH_OBJ);
if you're trying to get the rows from the database, the function you need is mysqli_stmt::fetch(), not mysqli_stmt::fetch_metadata()
You're also missing a few steps. When using prepared statements, you must specify the fields you would like to return instead of using the star wildcard, and then use mysqli_stmt::bind_result() to specify which variables the database fields should be placed in.
If you're more familiar with the original MySQL extension, prepared statements have a different process to use. If your select statement has a parameter (eg., "WHERE value=?") prepared statements are definitely recommended, but for your simple query, mysqli:query() would be sufficient, and not very different from the process of mysql_query()
I believe the problem is that mysqli_stmt::result_metadata() returns a mysqli_result object without any of the actual results — it only holds metadata.
So what you want to do is use $result = $statement->bind_result(...) and then call $result->fetch() repeatedly to get the results.
One of the comments under the bind-result() article shows how to do this for a query like yours, where you don't necessarily know all of the columns being returned.

Categories