This question already has an answer here:
Bind multiple parameters into mysqli query
(1 answer)
Closed 5 years ago.
I have been trying to use call_user_func_array()but dont seem to get it right.
$sql_sentence = "SELECT * FROM test_table WHERE Fag = ? AND (" . $sql_subject . ") AND (" . $sql_grade . ") AND (" . $sql_type . ")";
$sql = $conn->prepare($sql_sentence);
$allarrays = array_merge(array('ssss'),array($_POST['Fag']),$_POST['subject'],$_POST['Grade'],$_POST['Type']);
//testing to see if it prints out right values of array.
for ($x = 0; $x < count($allarrays); $x++) {
echo "The number $x is $allarrays[$x] <br>";
}
call_user_func_array(array($sql, "bind_param"),$allarrays);
$sql->execute();
But I get this error Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, and it points it to line call_user_func....
When I print out the SQL sentence it looks like this:
SELECT * FROM test_table WHERE Fag = ? AND (Subject LIKE ?) AND (Grade LIKE ?) AND (Type LIKE ?)
and all array-values are right, and the first array value is 'ssss', and after the first array comes four arrays with different values.
Have I done anything wrong here?
Do you need more code?
EDIT: Can you open this question. I found an answer which was different than the similar question! Think it should be printed here.
call_user_func_array expects its first argument to be a callable not an array:
mixed call_user_func_array ( callable $callback , array $param_arr )
Which function are trying to call, exactly? mysqli_stmt::bind_param()?
If so, it would need to look something like this:
call_user_func_array(array($stmt, 'bind_param'), array('s', $_POST['Fag']) );
Related
This question already has answers here:
Use an array in a mysqli prepared statement: `WHERE .. IN(..)` query [duplicate]
(8 answers)
Closed 11 months ago.
I'm trying to create a select query with dynamic where clause and dynamic parameters but I always get error :
Warning: mysqli_stmt::bind_param(): Number of elements in type
definition string doesn't match number of bind variables
Which I sincerely do not understand since it seems the count is alright. So this is what the code really looks like in its rude format. I can't see what I'm doing wrong.
//get variables
$mediaArray ='Facebook,Twitter,Twitch,';
$otherMedia = 'House';
//convert string to array
$socialArray = explode(',', $mediaArray)
//declare some variables to be used later
$andwhere = '';
$bp = '';
$socialmarray = ''
//get every value from array of social media
foreach($socialArray as $socialmedia){
$socialmarray .=$socialmedia.',';
$andwhere .= " AND socialmedianame=?";
$bp .='s';
}
//test strings
echo $wheres = $andwhere;//AND socialmedianame=? AND socialmedianame=? AND socialmedianame=?
echo $bip = $bp.'s';//ssss
echo $validarayy = rtrim($socialmarray,',');//Facebook,Twitter,Twitch
//select query
$selectquery = $conn->prepare("select * from mediaservices where socialmedianame=? $wheres");
$selectquery->bind_param("$bip",$otherMedia,$validarayy);
$selectquery->execute();
$resultquery = $selectquery->get_result();
Because:
You are using user-supplied data, you must assume that your query is vulnerable to a malicious injection attack and
the amount of data that is to be built into the query is variable/indefinite and
you are only writing conditional checks on a single table column
You should use a prepared statement and merge all of the WHERE clause logic into a single IN statement.
Building this dynamic prepared statement is more convoluted (in terms of syntax) than using pdo, but it doesn't mean that you need to abandon mysqli simply because of this task.
$mediaArray ='Facebook,Twitter,Twitch,';
$otherMedia = 'House';
$media = array_unique(explode(',', $mediaArray . $otherMedia));
$count = count($media);
$conn = new mysqli("localhost", "root", "", "myDB");
$sql = "SELECT * FROM mediaservices";
if ($count) {
$stmt = $conn->prepare("$sql WHERE socialmedianame IN (" . implode(',', array_fill(0, $count, '?')) . ")");
$stmt->bind_param(str_repeat('s', $count), ...$media);
$stmt->execute();
$result = $stmt->get_result();
} else {
$result = $conn->query($sql);
}
foreach ($result as $row) {
// access values like $row['socialmedianame']
}
For anyone looking for similar dynamic querying techniques:
SELECT with dynamic number of LIKE conditions
INSERT dynamic number of rows with one execute() call
In your query:
$selectquery = $conn->prepare("select * from mediaservices where socialmedianame=? $wheres");
The ? represents one parameter to pass in, and the evaluation of $wheres adds another three, giving you four total parameters.
bind_param() should take a string representing the types of the variables to insert as the first parameter, and the variables themselves as the subsequent parameters.
In your bind:
$selectquery->bind_param("$bip",$otherMedia,$validarayy);
$bip evaluates to ssss and $otherMedia is a single string ("House"). You might expect $validarayy to be three strings, but rtrim() returns a string. Thus, it is only one string ("Facebook,Twitter,Twitch"). You pass through two variables when the query is expecting four:
$conn->prepare("select * from mediaservices where socialmedianame=House AND socialmedianame=Facebook,Twitter,Twitch AND socialmedianame=? AND socialmedianame=? AND socialmedianame=?"
To correct this, you'll want to convert $validarayy back to an array, and use the index for the various inputs:
$socialmarray2 = explode(',', $validarayy);
$selectquery->bind_param("$bip", $otherMedia, $socialmarray2[0], $socialmarray2[1], $socialmarray2[2]);
Also note that your sample code has a few missing semicolons; you'll need to fix these in order for your code to work correctly.
This can be seen working here.
Finally, note that even if you were to split the three strings out correctly, the selection of ... AND socialmedianame=Facebook AND socialmedianame=Twitter AND socialmedianame=Twitch will never match any results; socialmedianame can only contain one value. You're probably looking to substitute your AND statements with OR statements.
This question already has answers here:
mysqli bind_param() expected to be a reference, value given
(3 answers)
Closed 6 years ago.
I am trying to implement dynamic sql query so that users has flexibility to use one or more filters to dig out the data he wants. I am using prepared statements to ensure that there is no SQL Injection. I am using WAMP Server 64 bit.
I referred to this article for writing my code: Sample
Following is my code:
$myqry="SELECT * FROM students WHERE ";
$initflag=0; //controls the first clause without AND and rest with AND
$paramtypes=array();
$paramvalues=array();
$params=array();
if(!empty($_POST['awr_admyear']))
{
$myqry.= "YEAR(adm_date)=? ";
$initflag=1;
$paramtypes[]='s';
$paramvalues[]=$_POST['awr_admyear'];
}
if(!empty($_POST['awr_admfrom']) && !empty($_POST['awr_admto']))
{
if($initflag==0)
$myqry.= "YEAR(adm_date) BETWEEN ? AND ? ";
else
$myqry.= "AND YEAR(adm_date) BETWEEN ? AND ? ";
$initflag=1;
$paramtype[]='s';
$paramtype[]='s';
$paramvalues[]=$_POST['awr_admfrom'];
$paramvalues[]=$_POST['awr_admto'];
}
if(!empty($_POST['awradm_no']))
{
if($initflag==0)
$myqry.= "adm_no LIKE ? ";
else
$myqry.= "AND adm_no LIKE ? ";
$initflag=1;
$paramtype[]='s';
$paramvalues[]=$_POST['awradm_no'];
}
$params = array_merge($paramtype,$paramvalues);
if(isset($myqry) && !(empty($myqry)))
{
if($result1 = $mysqli->prepare($myqry))
{
call_user_func_array(array($result1, 'bind_param'), $params);
if($result1->execute())
{
$finrest=$result1->get_result();
while($row= $finrest->fetch_assoc())
{
//and so on
I am getting the following error:
Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value given in..................
Where I am going wrong and what is the solution?
1) Follow this answer, mentioned here: mysqli bind_param() expected to be a reference, value given
2) Do the following changes:
$params = array_merge($paramtype,$paramvalues);
Replace it with:
$params[] = implode("", $paramtype);
$params = array_merge($params, $paramvalues);
$paramtype is array but bind_param needs first parameter should be string.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am using this PHP function:
if(!function_exists("SelectQuery2")) {
function SelectQuery2($table, array $where) {
//PDO
global $pdo_conn;
$sql = "SELECT * FROM `$table` ";
$values = null;
if ($where) {
$sql .= "WHERE " . implode(" AND ", array_map(function ($c) { return "`$c` = ?"; }, array_keys($where)));
$values = array_values($where);
}
$stmt = $pdo_conn->prepare($sql);
$stmt->execute($values);
}
}
And I am calling it here:
$where = array(" ticketnumber = ".$_GET["seq"]." ");
$ticket=SelectQuery2("tickets", $where);
$ticket = $ticket[0];
but I am not getting any results.
I use $ticket["column_name"] to show my results.
What could be the problem?
If you are creating such a complicated function, why don't you check first the returning values?
I did this test
function SelectQuery2($table, array $where) {
$sql = "SELECT * FROM `$table` ";
$values = null;
if ($where) {
$sql .= "WHERE " . implode(" AND ", array_map(function ($c) { return "`$c` = ?"; }, array_keys($where)));
$values = array_values($where);
}
return array($sql, $values);
}
$where = array("ticketnumber = asdasdasd", "ticketbla = dfgdfgdfg");
$ticket=SelectQuery2("tickets", $where);
var_dump($ticket);
And the output is:
array (size=2)
0 => string 'SELECT * FROM `tickets` WHERE `0` = ? AND `1` = ?' (length=49)
1 =>
array (size=2)
0 => string 'ticketnumber = asdasdasd' (length=26)
1 => string 'ticketbla = dfgdfgdfg' (length=21)
So, are you expecting your column names to be 0 and 1, instead of the real column names?
I guess - no. You need array_keys() in the closure, but you are passing array $where as numeric array (with only values), so the keys are 0, 1, etc...
You would need an associative array, which passes the column name as key because the closure requires it this way, and the value as value because the PDOStatement::execute requires it this way, when not using named placeholders, but ?.
http://www.php.net/manual/en/pdostatement.execute.php
The appropriate example from here is:
<?php
/* Execute a prepared statement by passing an array of insert values */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute(array($calories, $colour));
?>
Which says that execute() here accepts the values 150 and red as array values (array(150, 'red')) which in your case will be (array($_GET["seq"])).
The right example of the passed array should be:
$where = array('ticketnumber' => $_GET["seq"]);
If you need multiple column names and values, just add more key => value pairs.
$where = array(
'ticketnumber' => $_GET["seq"],
'ticket_owner' => $_GET['owner'],
'ticket_etc' => $_GET['etc']
);
But, here you have some disadvantages:
Your function is strictly complicated to rules col1 = val1 AND col2 = val2 AND.... Your SELECT query is only for simple data extraction. You barely can use SQL functions, HAVING clauses, date operators, BETWEEN, nor <; >.
That's why I would not suggest this variant of wrapping PDO. At its nature, PDO is already some kind of wrapper. At least don't make the query string dynamic. You can try to wrap the prepare(), execute(), fetch(), but stop there. Also don't do it in procedural PHP functions. It will just increase the agony of bad design, such as using globals, because your PDO object is not shared between them.
i need help with my function thet i build , i trying to use MYSQLI prepare but i am not so good .
this is my function :
function insertToDb($table,$rowsarray,$valuequestionmarks,$lenstrings,$valarray){
$this->mysqli->set_charset("utf8");
if ($insert_stmt = $this->mysqli->prepare(
"INSERT INTO $table ($rowsarray)
VALUES
($valuequestionmarks)"
))
{
$insert_stmt->bind_param("$lenstrings",$valarray);
// Execute the prepared query.
if(!$insert_stmt->execute())
{
die("Execute failed: (" . $insert_stmt->errno . ") " . $insert_stmt->error);
}
}
}
And this is how i call :
$img = "something.jpg";
$uip = ulUtils::GetRemoteIP(false);
$table='forgotpassqm';
$rowsarray = 'email,text,img,ip';
$valuequestionmarks ='?,?,?,?';
$lenstrings ='ssss';
$valarray ='$email,$text,$img,$uip';
$func->insertToDb($table,$rowsarray,$valuequestionmarks,$lenstrings,$valarray);
And i keep get this error :
Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables
And the execute error :
Execute failed: (2031) No data supplied for parameters in prepared statement
i tryed allot of combination none work , i read other question none as my , and none worked or help either.
And i know this is about the ssss , but i using 4 and its seem to be alright so where i wrong here ?
Thanks allot.
EDIT :
$table output : forgotpassqm .
$rowsaray output: email,text,img,ip .
$valuequestionmarks output : ?,?,?,? .
$lenstrings output: ssss.
$valarray output: $email,$text,$img,$uip.
I think the problem is at $valarray.
Judging by the looks of it you are attempting to send a comma-delimited list of variables as an array (not how an array works) and you are using single quotes so variables aren't being interpolated to their values.
bind_param() expects a list of arguments after the type definitions. You aren't sending a list, you are sending the string '$email,$text,$img,$uip'.
Your call to that function should look like this:
$stmt->bind_param("ssss", $email, $text, $img, $uip);
So, I have this PHP code:
$tabid = getTabid($module);
if($tabid==9)
$tabid="9,16";
$sql = "select * from field ";
$sql.= " where field.tabid in(?) and";
Now, how exactly does the ? work here? I vaguely understand that in PHP, ?: is a ternary operator, but the colon isn't being used here, and ? is part of a Postgresql query anyway.
The final query looks a bit like this:
select * from field where field.tabid in('9,16')
So, the question mark is replaced by the contents of $tabid, how does that happen?
The issue is that ('9,16') is not accepted by Postgres as an integer, it needs to be written like (9,16), so how do I do that? How do I remove the apostrophes?
Thanks a lot for the help, have a good day!
edit: More code was requested:
$sql.= " field.displaytype in (1,2,3) and field.presence in (0,2)";
followed by if statements, I think this is the relevant one:
if($tabid == 9 || $tabid==16)
{
$sql.= " and field.fieldname not in('notime','duration_minutes','duration_hours')";
}
$sql.= " group by field.fieldlabel order by block,sequence";
$params = array($tabid);
//Running the query.
$result = $adb->pquery($sql, $params);
Oh, I think I see now, I think it is a place holder, a part of the pquery function:
function pquery($sql, $params, $dieOnError=false, $msg='') {
Stuff
$sql = $this->convert2Sql($sql, $params);
}
Now, this is where it seems to get fun, here's part of the convert2Sql function:
function convert2Sql($ps, $vals) {
for($index = 0; $index < count($vals); $index++) {
if(is_string($vals[$index])) {
if($vals[$index] == '') {
$vals[$index] = "NULL";
}
else {
$vals[$index] = "'".$this->sql_escape_string($vals[$index]). "'";
}
}
}
$sql = preg_replace_callback("/('[^']*')|(\"[^\"]*\")|([?])/", array(new PreparedQMark2SqlValue($vals),"call"), $ps);
return $sql;
}
The problem I think lies in the
$vals[$index] = "'".$this->sql_escape_string($vals[$index]). "'"; line.
The sql_escape_string($str) function just returns pg_escape_string($str).
Sorry for the super long edit, but I still haven't been able to get past I am afraid, thanks for all the help!
Edit 2: I fixed the problem, all it took was changin $tabid = "9,16" to $tabid = array(9,16). I have no idea why, oh and I also had to remove the group by statement because Postgresql requires every field to be placed in that statement.
it is a positional parameter for a prepared statement
See: http://php.net/manual/en/function.pg-prepare.php
You don't actually 'remove' the quotes, you have to pass SQL array of ints instead of a string value into the parameter when doing pg_execute
An example:
// Assume that $values[] is an array containing the values you are interested in.
$values = array(1, 4, 5, 8);
// To select a variable number of arguments using pg_query() you can use:
$valuelist = implode(', ', $values);
// You may therefore assume that the following will work.
$query = 'SELECT * FROM table1 WHERE col1 IN ($1)';
$result = pg_query_params($query, array($valuelist))
or die(pg_last_error());
// Produces error message: 'ERROR: invalid input syntax for integer'
// It only works when a SINGLE value specified.
Instead you must use the following approach:
$valuelist = '{' . implode(', ', $values . '}'
$query = 'SELECT * FROM table1 WHERE col1 = ANY ($1)';
$result = pg_query_params($query, array($valuelist));