Optionally make use of bound parameters in PDO query? - php

I have a series of queries to loop through and execute using PDO.
The queries may make use of zero or more of the following 3 bound values, ":valA", ":valB" and ":valC".
At runtime I don't know which of these three parameter a query might use. But the values of these parameters will be the same for each query I loop through.
If I bind all three to a prepared query and the query does not make use of all the parameters, PDO will error.
I.e.
<?php
$stmt = $pdo->prepare('SELECT * FROM table WHERE col = :valA OR col = valB');
$stmt->execute(array(':valA' => 'a', ':valB' => 'b', ':valC' => 'c'); // Results in an error because the query does makes use of :valC.
Is there a method for binding a parameter without making it required to be used by a prepared query?
I thought I wuold be able to catch the exception and allow the code to resume, but the query won't execute regardless of the error mode set for PDO.
Note that this question is different to the suggested duplicate of, Ignore particular WHERE criteria. In that question, the query needed to be crafted to suit optional values supplied by a user. I this case, the values are hardcoded by the application, and the queries are stored in a database. The application does not know which params a query may make use of, so it needs to make them all available.
Obviously I can regex check for params, but it could be tripped up by a string that happen to contain the parameter name.
The queries could also be stored with additional properties to indicate which params it makes use of, but I would prefer to not have to do this.

There is a way to do this with PDO. The methods bindParam() and bindValue() return false or throw an exception if you try to bind to a parameter that doesn't appear in the query.
But it only works if you set:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Example:
$stmt = $pdo->prepare("INSERT INTO foo (test, boolcol) VALUES (:valA, :valB)");
if (!$stmt->bindParam("valA", $foo))
{
echo "error, no param 'valA'\n";
}
if (!$stmt->bindParam("valB", $foo))
{
echo "error, no param 'valB'\n";
}
if (!$stmt->bindParam("valC", $foo))
{
echo "error, no param 'valC'\n";
}
Outputs:
PHP Warning: PDOStatement::bindParam(): SQLSTATE[HY093]:
Invalid parameter number: parameter was not defined in /home/billkarwin/pdo.php on line 18
error, no param 'valC'
If you set $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); then it throws an exception instead of a warning, and you could wrap each bindParam() in a try/catch block:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]:
Invalid parameter number: parameter was not defined' in /home/billkarwin/pdo.php:18
Stack trace:
#0 /home/billkarwin/pdo.php(18): PDOStatement->bindParam('valC', 'foo')
#1 {main}
thrown in /home/billkarwin/pdo.php on line 18

Related

search bar error: function bind_param() on a non-object [duplicate]

This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed 6 years ago.
I am trying to bind a variable in this prepared statement, but i keep receiving the error:
Call to a member function bind_param() on a non-object
The function is called, and variables are passed to it. When i change the function to just echo the variable, the variable prints on the page fine, but if i try to bind it here i receive the error. can anyone help?
//CALL FROM PAGE ONE
check($username);
//FUNCTION ON PAGE 2
function check($username){
$DBH = getDBH();
$qSelect = $DBH->prepare("SELECT * FROM users WHERE username = ?");
$qSelect->bind_param("s", $username);
}
i know the function is not completely written here, but that shouldn't be a problem. I don't understand why i am receiving this error.
Well, one reason prepare() can fail is if the sql statement sent to it is not valid in the current DB.
prepare() will then return false.
Eg - if the table name is not correct or one or more field in the query does not exist.
as the error-message says, $qSelect seems to be not an object. try to debug this by using var_dump($qSelect); right after your prepare-call. also check if getDBH() returns what you need.
sounds like the prepare-call fails (don't know why) and so it returns false - false is not an object, so you can't call bind_param() on that.
EDIT: you havn't given the info, but it looks like you're using PHP's PDO. In that case, take a look at the documentation.
If the database server successfully
prepares the statement, PDO::prepare()
returns a PDOStatement object. If the
database server cannot successfully
prepare the statement, PDO::prepare()
returns FALSE or emits PDOException
(depending on error handling).
You should configure your server to return those PDO-Exceptions, which would tell you why the prepare call fails.
i'm using the mysqli approach as well and got the same error when I created another instance of mysqli before closing the first instance. So its important to use close() before starting the same piece of code. For example:
$DBH = getDBH();
$qSelect = $DBH->prepare("SELECT * FROM users WHERE username = ?");
$qSelect->bind_param("s", $username);
$qSelect->close(); // <--- use close before calling the same function( wich contains $DBH code) again;
It appears that prepare is quite dumb. It doesn't rely query entirely into the MySQL side, by this, I mean, if in your query, you have a table that happens to have the same name of a keyword, say "user", "order", ..., it just doesn't recognize it as a table, but rather as what the keyword commands actually do, so the query turns out to be a mess and the prepare just fail.
To fix this is simple, you have to type it in the "correct" way adding "`" in both sides of the table name. Example:
`user`, `order`, `...`
It's correct, yet, I find it silly from prepare to have this behavior.
I am trying to help other people with little experience in PHP like me.
In my case, this error occurred because I had an SQL syntax error. The console stack trace did not show the problem.
When I fixed the SQL, the error was gone.
Check the permissions of the user in database. User without "insert" permission causes "Call to a member function bind_param() on a non-object" message error too, when trying to insert.

Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdoc

I am Getting Warning Like Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdoc And Values are not Going to insert in database.
Can anybody please me I am Stuck With Problem From Many Days
Here is code:-
<?php
if(isset($_POST['btn_Add']))
{
// Step 1: Establish a connection
$conn = new PDO("mysql:host=localhost; dbname=DbName", 'root', '');
$MaxId ="2";
$Feild_1 =$_POST['txt_Feild1']; //datatype int
$Feild_2 =$_POST['txt_Feild2']; //datatype varchar
$Feild_3 =$_POST['txt_Feild3']; //varchar
// Step 2: Construct a query
$insert_query=$conn->prepare("Insert INTO Dbname (Max_Id, Feild_1, Feild_2, Feild_3)
values (:Max_Id,:Feild_1, :Feild_2, :Feild_3,");
// Step 3: Send the query
$result=$conn->query($insert_query);
// STEP 4:Bind The Placeholder name to specific Script variables
$insert_query->bindParam(':Max_Id', $Max_Id);
$insert_query->bindParam(':Feild_1', $Field_1);
$insert_query->bindParam(':Feild_2', $Field_1);
$insert_query->bindParam(':Feild_3', $Field_1);
//Step 5 Execute Query
$insert_query->execute();
}//OUTER IF END
?>
PDO Warning :-Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdocs\BSNL Project\Add_Pin_Unpin_File(Without Auto Increment).php on line 109
[]
Step 1 - Fix your SQL:
So, with the code you've given, you've actually got an SQL error. If we take the SQL out of the PHP, it looks like...
Insert INTO Dbname (Max_Id, Feild_1, Feild_2, Feild_3)
values (:Max_Id,:Feild_1, :Feild_2, :Feild_3,
So the issue with this is that, first, you have a trailing comma that shouldn't be there, and you're missing a trailing ) that closes the values part of the query.
As a side note, you're using Dbname as a table name. Whether this is correct or not, we don't know, that depends on you.
Step 2 - Use PDO correctly:
The warning message you've provided is;
PDO Warning :-Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdocs\BSNL Project\Add_Pin_Unpin_File(Without Auto Increment).php on line 109
If you look at the documentation the query method expects at least one parameter which has to be a string. This method returns an instance of PDOStatement and runs an execute straight away. As far as I know, it does not support prepared statements.
So the warning comes because you've called prepare with your SQL statement which returns an object of type PDOStatment, and then pass that returned object as the first parameter which as expected throws a warning saying that you've not passed a string.
By simply removing the line $result=$conn->query($insert_query); you will remove the warning message without causing other issues as it's not necessary anyway as you bind and then execute the query manually afterwards.
If there are further issues, then I'd suggest you have a look at setting the exception mode on your PDO connection variable and seeing what comes up.
Step 3 - Fix your binds
The final issue that I can see is with the following...
$insert_query->bindParam(':Max_Id', $Max_Id);
You bind $Max_Id but earlier in your code, you actually create the variable $MaxId.
The same goes for the fields. You bind $Field_1, but your actual variable is $Feild_1.
Finally, you're binding the same variable for multiple placeholders which doesn't seem quite right when you appear to have defined different variables for each one.
You need to call execute for the prepared queries.
http://php.net/manual/en/pdostatement.execute.php
$insert_query->execute();

PDO: Binding data trough an array when selecting

I am trying to set an array containig all required parameters for my PDO queries on a file, and the first of those queries is a SELECT making use of just one parameter.
$data = array(
'us_id' => $_POST['us_id'],
'us_credits' => $_POST['us_credits'],
'us_access' => $_POST['us_access']
);
$selectUsers= "SELECT * FROM ws_users WHERE us_id= :us_id";
$statementSelectUsers = $pdo->prepare($selectUsers);
$statementSelectUsers->execute($data);
$result = $statementSelectUsers->fetch(PDO::FETCH_ASSOC);
$us_fk_ui_id = $result['us_fk_ui_id'];
On executing, a Fatal Error emerges:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[HY093]: Invalid parameter number: number of bound variables
does not match number of tokens' in
C:\wamp\www\waisap\actions\ad_updateUserInfo.php on line 25
Line 25 is the $statementSelectUsers->execute($data); line
As far as I've learned, a SELECT query on PDO does not need to execute(), but if no query is executed, I can not pass binded data contained on my array to query's placeholders. Is this the reason for the error? How to pass an array to be applied on my SELECT query's placeholders?
Let me repeat what I told you in the other answer 5 minutes ago:
array keys have to match placeholders in the query. If your queries have different sets of placeholders, you will need different arrays as well.
So, that's the reason for this problem.
As far as I've learned, a SELECT query on PDO does not need to execute(),
You've learned it wrong. You have to execute everything that has been prepared.
First, create $data array with only one element and use it for SELECT
$data = array('us_id' => $_POST['us_id']);
$stmt = $pdo->prepare("SELECT us_fk_ui_id FROM ws_users WHERE us_id= :us_id");
$stmt->execute($data);
$us_fk_ui_id = $stmt->fetchColumn();
for the later queries add other items to this array

PHP - Call to a member function bind_param() on a non-object - Prepared Statement [duplicate]

This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed 6 years ago.
I am trying to bind a variable in this prepared statement, but i keep receiving the error:
Call to a member function bind_param() on a non-object
The function is called, and variables are passed to it. When i change the function to just echo the variable, the variable prints on the page fine, but if i try to bind it here i receive the error. can anyone help?
//CALL FROM PAGE ONE
check($username);
//FUNCTION ON PAGE 2
function check($username){
$DBH = getDBH();
$qSelect = $DBH->prepare("SELECT * FROM users WHERE username = ?");
$qSelect->bind_param("s", $username);
}
i know the function is not completely written here, but that shouldn't be a problem. I don't understand why i am receiving this error.
Well, one reason prepare() can fail is if the sql statement sent to it is not valid in the current DB.
prepare() will then return false.
Eg - if the table name is not correct or one or more field in the query does not exist.
as the error-message says, $qSelect seems to be not an object. try to debug this by using var_dump($qSelect); right after your prepare-call. also check if getDBH() returns what you need.
sounds like the prepare-call fails (don't know why) and so it returns false - false is not an object, so you can't call bind_param() on that.
EDIT: you havn't given the info, but it looks like you're using PHP's PDO. In that case, take a look at the documentation.
If the database server successfully
prepares the statement, PDO::prepare()
returns a PDOStatement object. If the
database server cannot successfully
prepare the statement, PDO::prepare()
returns FALSE or emits PDOException
(depending on error handling).
You should configure your server to return those PDO-Exceptions, which would tell you why the prepare call fails.
i'm using the mysqli approach as well and got the same error when I created another instance of mysqli before closing the first instance. So its important to use close() before starting the same piece of code. For example:
$DBH = getDBH();
$qSelect = $DBH->prepare("SELECT * FROM users WHERE username = ?");
$qSelect->bind_param("s", $username);
$qSelect->close(); // <--- use close before calling the same function( wich contains $DBH code) again;
It appears that prepare is quite dumb. It doesn't rely query entirely into the MySQL side, by this, I mean, if in your query, you have a table that happens to have the same name of a keyword, say "user", "order", ..., it just doesn't recognize it as a table, but rather as what the keyword commands actually do, so the query turns out to be a mess and the prepare just fail.
To fix this is simple, you have to type it in the "correct" way adding "`" in both sides of the table name. Example:
`user`, `order`, `...`
It's correct, yet, I find it silly from prepare to have this behavior.
I am trying to help other people with little experience in PHP like me.
In my case, this error occurred because I had an SQL syntax error. The console stack trace did not show the problem.
When I fixed the SQL, the error was gone.
Check the permissions of the user in database. User without "insert" permission causes "Call to a member function bind_param() on a non-object" message error too, when trying to insert.

PDO (mysql) Invalid parameter number: parameter was not defined

I've found so many existing questions asking about this error but none of them relate to my code's situation so despite searching for a while I've had to start a new question.
I'm writing a PDO prepared statement in PHP and i'm getting the error code:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number: parameter was not defined' in...
The query that has been build so far is:
SELECT * FROM esl_comments, esl_articles WHERE esl_comments.commentSet=:esl_comments.commentSet AND esl_comments.commentSetInstanceID=:esl_comments.commentSetInstanceID AND esl_comments.commentVisible=:esl_comments.commentVisible AND esl_comments.commentID=:esl_comments.commentID;
And the data is being passed to the function which attempts to execute the query just fine. I've echo'ed it and it appears as:
esl_comments.commentSet - article
esl_comments.commentSetInstanceID - esl_articles.articleID
esl_comments.commentVisible - Y
esl_comments.commentID - 2
So there are four placeholders in the query, and all four are being satisfied with data but when I try to execute the query after binding it is giving the above error.
Does anyone have any ideas what may be causing it?
Placeholders must be alphanumeric or underscore.
:esl_comments.commentSet is not a valid placeholder. Try just :commentSet instead.
(And of course the other ones will need to be replaced as well)

Categories