PHP MySQL Query don't deliver multidimensional Array - php

SOLVED: Reason Can I parameterize the table name in a prepared statement?
I have a very simple Query to collect data from a two column table in MySQL. Normally it worked but for some reason I know receive the error: Undefined offset: 1
$query_select = ("SELECT ?, ? FROM _HOOFDRUBRIEK");
$stmt = $mysqli->prepare($query_select);
$stmt->bind_param("ss", $column1, $column2);
$stmt->execute();
$stmt->store_result();
//$count = $stmt->num_rows;
//echo $count;
/die();
$stmt->bind_result( $key_hoofdrubriek ,
$descr_hoofdrubriek );
$stmt->fetch();
$hoofdrubriek[] = array('key' =>$key_hoofdrubriek ,
'descr' =>$descr_hoofdrubriek );
//Here I request the variable, what occurs the error
$var = $hoofdrubriek[1]['descr'];
echo 'Show here what's in the var: '.$var ;
Does anyone know why I get this error, because from my point of view, a multidimensional array can be called by $array_name[row][column];

You are mistinpreting how that works. Result bind parameters are just bound in order to the selected field. You still need to select normal fields as usual.
Moreover, you cannot specify field names as input parameters. In your situation, you select two constant values, namely the strings you pass as input parameters. This is why you get the field names in the result instead of the values of those fields. The parameters are just string values, so the query that is executed would look like this:
SELECT 'key_hoofdrubriek', 'descr_hoofdrubriek' FROM FROM RGS_HOOFDRUBRIEK
So, skip the question marks and the input bind parameters altogether and build the query like so:
$query_select = ("SELECT key_hoofdrubriek, descr_hoofdrubriek FROM RGS_HOOFDRUBRIEK");
Or, if you must, by using PHP variables in the statement:
$query_select = ("SELECT $column1, $column2 FROM RGS_HOOFDRUBRIEK");
For reading, you can of course still use bind_result.

You can't use placeholders for column names, they're always treated as expressions. So your prepared query is equivalent to writing:
SELECT 'key_hoofdrubriek', 'descr_hoofdrubriek' FROM RGS_HOOFDRUBIEK
This just returns those literal strings for each row in the table, not the values in the columns with those names.
If you need to determine the column names dynamically, you have to use variable substitution or concatenation, you can't use placeholders:
$query_select = "SELECT $column1, $column2 FROM RGS_HOOFDRUBRIEK";

Related

SELECT ? FROM table WHERE id = ? not working correctly [duplicate]

This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 6 years ago.
I've got a little question. I want to get specific information out of my database via mysqli query:
public function get_searchorder_single_information($soid, $information) {
global $mysqli;
$stmt = $mysqli->prepare("SELECT ? FROM pr_hr_searchorders WHERE id = ?");
$stmt->bind_param('si', $information, $soid);
$stmt->execute();
$stmt->bind_result($result);
$stmt->fetch();
echo $result;
$stmt->close();
}
In my example, $information is set 'job', but it can have other values, too (e.g. 'salary'). When I try to use my query with this variable, echo outputs just 'job' and not the value that is saved in my database. When I write 'job' instead of the '?', echo outputs the correct value.
So now I could make a function for each information I search, but this would end in spaghetti code. So I ask you if there is any possibility to use my search query like above with correct output. How would I do that?
Thanks in advance and sorry for my bad english writing.
Read documentation : http://php.net/manual/en/mysqli.prepare.php
The markers are legal only in certain places in SQL statements. For
example, they are allowed in the VALUES() list of an INSERT statement
(to specify column values for a row), or in a comparison with a column
in a WHERE clause to specify a comparison value. However, they are not
allowed for identifiers (such as table or column names), in the select
list that names the columns to be returned by a SELECT statement, or
to specify both operands of a binary operator such as the = equal
sign. The latter restriction is necessary because it would be
impossible to determine the parameter type. It's not allowed to
compare marker with NULL by ? IS NULL too. In general, parameters are
legal only in Data Manipulation Language (DML) statements, and not in
Data Definition Language (DDL) statements.
Modify your code :
$stmt= $mysqli->prepare("SELECT $information FROM pr_hr_searchorders WHERE id = ?");
$stmt->bind_param('i', $soid);
Change your code to
public function get_searchorder_single_information($soid, $information) {
global $mysqli;
$query = "SELECT".$information." FROM pr_hr_searchorders WHERE id = ?"
$stmt = $mysqli->prepare($query);
$stmt->bind_param('si', $soid);
$stmt->execute();
$stmt->bind_result($result);
$stmt->fetch();
echo $result;
$stmt->close();
}
Then you will get the desired result

PDO Prepare Not Replacing Named Placeholders

I have tried using named placeholder to fill in the data as shown here:
$STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes WHERE id NOT IN ( :noredo_ids ) ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id");
$STH->bindParam(':noredo_ids', $_GET["noredo"]);
$STH->setFetchMode(PDO::FETCH_ASSOC);
$STH->execute();
As well as trying
$arr2["ids"] = $_GET["noredo"];
$STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes WHERE id NOT IN ( :ids ) ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id");
$STH->setFetchMode(PDO::FETCH_ASSOC);
$STH->execute($arr2);
But neither of those are working. But when I try to manually put the string in instead of using placeholders, it does work:
$arr2["ids"] = $_GET["noredo"];
$STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes WHERE id NOT IN (". $arr2['ids'] .") ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id");
$STH->setFetchMode(PDO::FETCH_ASSOC);
$STH->execute();
Should I manually escape the string? Am I missing something obvious? Thanks!
I am not certain since PHP's documentation on named placeholders for prepared statements is kinda vague about this. http://php.net/manual/en/pdostatement.bindparam.php
But if $_GET['noredo'] is an array of IDs you need to first implode(',',$_GET['noredo']) before passing into the prepared statement, I do not believe that the placeholder replacement is smart enough to flatten the array into a comma separated list acceptable for use in IN().
And in PHP docs, the replacement is a single value and not an array of values, so (and this is where I'm fuzzy) I don't believe that it looks for :named_placeholder in the array you pass it.
But then again, I've only used the ? placeholder for prepared statements...
A query parameter always takes the place of one single scalar value in an SQL expression.
So if you expect $_GET["noredo"] to be an array or a comma-separated list of values, what you're doing won't work. The query will be run as if you did this:
WHERE id NOT IN ( '1,2,3,4' )
A quoted string value that contains a comma-separated list is not the same as a series of comma-separated values. It's one string, and in a numeric context SQL will convert '1,2,3,4' into the scalar number 1.
So you need to use multiple placeholders if you want to bind multiple values in an IN() predicate.
$id_array = (array) $_GET["noredo"];
$placeholders = implode(",", array_fill(0,count($id_array),"?"));
$STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes
WHERE id NOT IN ( $placeholders ) ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id");
$STH->execute($id_array);
The second example doesn't work because you used $arr2["ids"] instead of $arr2[":ids"] as far as I can tell. That is, you still have to use the full parameter name.
Also, you should make sure that the values you try to insert are properly sanitized and cannot cause a syntax error.

MySQLi prepare result not as expected

I am trying to retrieve one result from my database table 'members' using a prepared call.
$favid = 1;
$type = "favdeal";
$action = 1;
$user_id = 1;
$stmt = $mysqli->prepare("SELECT ? FROM members WHERE id=?");
$stmt->bind_param('ss', $type, $user_id);
$stmt->execute();
$stmt->bind_result($favs);
while ($stmt->fetch()) {
print($favs);
}
$stmt->close();
This is the only way i managed to get any kind of result.
The table has a column called 'favdeal' which has a value of '2' in it.
The result printed returns the name of the column not the value.
So my question is how do i get the value '2' instead of the name of the column?
You can't bind columns (or tables) from doing a SELECT as you have in SELECT ?.
Select an actual column.
Or, if you want to do it dynamically, you need to use a variable.
Example: SELECT $type <= that is allowed.
However, column names can be binded when using a WHERE clause.
Example: SELECT column FROM table WHERE column=?
which you are presently using => WHERE id=?
Consult the manual on bind_param()
http://www.php.net/manual/en/mysqli-stmt.bind-param.php
Footnotes:
If you happen to use an MySQL reserved word (it could happen), you will need to wrap your column's variable with backticks.
For example: (if using $type="from";) "from" being a reserved word.
SELECT `$type` FROM members WHERE id=?
For a list of MySQL reserved words, visit the following page:
http://dev.mysql.com/doc/refman/5.5/en/reserved-words.html

Outputting a select count(name) value in php pdo with mySql

$stmt = $conn->prepare('select count(names) as names from names where names = :name');
$stmt->bindParam(':name', $name);
$stmt->execute();
How do I output the value of names when doing a select count() using PDO without having to use a while loop or something similar?
I need the count value of names (1, 3 or 5 or whatever it is).
$count = $stmt->fetchColumn();
fetchColumn()
The select count(..) from ..-Statement always only outputs this column (the count of rows), so you cannot access the names. You will have to execute a statement only for getting the names, OR you can actually output the name by yourself, because you already have it in $name ;)

Using PDO in PHP to count all from database and the 'WHERE' is a variable that has to be cleaned

I'm trying to count all of the rows from an item list where the id matches a user input. I am switching all of my code from mysql to PDO as I have learned it is much better.
The code below is what I found to work in my situation.
$id = '0';
$sql="SELECT count(*) FROM item_list WHERE item_id = $id";
$data=$connMembers->query($sql)->fetchcolumn();
echo $data;
However, It is not safe for a live site due to sql injections.
I want to know how can I change it to work whare it sanatizes the user input.
I would prefer using a prepare and execute functions so the variables are kept seperately.
So is there something I can do?
This is where you start binding parameters. I prefer to do it using ? and one array for inputs.
Assuming $connMembers is your PDO object:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ?";
$input=array($id); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
To add more variables to your sql, just add another ? to the query and add the variable to your input.
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ? AND item_name=?";
$input=array($id, $name); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
OR you can use bindParam:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = :itemID";
$statement=$connMembers->prepare($sql);
$statement->bindParam(':itemID', $id);
/*Here I am binding parameters instead of passing
an array parameter to the execute() */
$statement->execute();
$data=$statement->fetchObject();
var_dump($data);

Categories