PDO bindParam vs. execute - php

I often see code using bindParam or bindValue with PDO. Is simply passing arguments to execute frowned upon for any reason?
I understand that bindParam actually binds to the variables and that you can set the type of parameter being bound with both bind methods, but what if you are only inserting strings?
$query = "SELECT col1 FROM t1 WHERE col2 = :col2 AND col3 = :col3 AND col4 = :col4";
$pdo->bindValue(':col2', 'col2');
$pdo->bindValue(':col3', 'col3');
$pdo->bindValue(':col4', 'col4');
I often see the above, but personally I prefer:
$pdo->execute(array(':col2' => 'col2', ':col3' => 'col3', ':col4' => 'col4'));
It is not as verbose and visually it makes more sense to me to have the inputs "going in" to the query together. However, I hardly ever see it used.
Is there a reason to prefer the bind methods over passing parameters to execute when you don't have to take advantage of the special behaviors of the former?

You might find bindParam used when you just want to bind a variable reference to a parameter in the query, but perhaps still need to do some manipulations on it and only want the value of the variable calculated at time of query execution. It also allows you to do more complex things like bind a parameter to a stored procedure call and have the returned value updated into the bound variable.
For more, see the bindParam documentation, bindValue documentation and execute documentation.
For example
$col1 = 'some_value';
$pdo->bindParam(':col1', $col1);
$col1 = 'some_other_value';
$pdo->execute(); // would use 'some_other_value' for ':col1' parameter
bindValue and passing an array to execute behave in much the same way as the parameter value is fixed at that point and SQL executed accordingly.
Following the same example above, but using bindValue
$col1 = 'some_value';
$pdo->bindValue(':col1', $col1);
$col1 = 'some_other_value';
$pdo->execute(); // would use 'some_value' for ':col1' parameter
When passing values directly in execute all values are treated as strings (even if integer value is provided). So if you need to enforce data types, you should always use bindValue or bindParam.
I think you might see bind* used more than execute(array) as many consider it to be better coding practice to explicitly define data types in parameter declarations.

By passing the parameters along with the $pdo->execute() method, all values in the array with be passed, as PDO::PARAM_STR to the statement with the $pdo->bindParam() function.
The main difference that I can see now, is that with the $pdo->bindParam() function, you can define the data type passed along, using the PDO::PARAM_* constants as described in the PHP.net manual

Simple,
the value of bindParam may change but the value of bindValue can not change.
Example:
$someVal=10;
$someVal2=20;
/* In bindParam, the value argument is not bound and
will be changed if we change its value before execute.
*/
$ref->bindParam(':someCol',$someVal);
$someVal=$someVal2;
$ref->execute();
//someCol=20
/* In bindValue, the value argument is bound and
never changed if we change its value before execute.
*/
$ref->bindValue(':someCol',$someVal);
// here assignment is referral (&$someVal)
$someVal=$someVal2;
$ref->execute();
//someCol=10

Related

PHP PDO Bind or Execute [duplicate]

I often see code using bindParam or bindValue with PDO. Is simply passing arguments to execute frowned upon for any reason?
I understand that bindParam actually binds to the variables and that you can set the type of parameter being bound with both bind methods, but what if you are only inserting strings?
$query = "SELECT col1 FROM t1 WHERE col2 = :col2 AND col3 = :col3 AND col4 = :col4";
$pdo->bindValue(':col2', 'col2');
$pdo->bindValue(':col3', 'col3');
$pdo->bindValue(':col4', 'col4');
I often see the above, but personally I prefer:
$pdo->execute(array(':col2' => 'col2', ':col3' => 'col3', ':col4' => 'col4'));
It is not as verbose and visually it makes more sense to me to have the inputs "going in" to the query together. However, I hardly ever see it used.
Is there a reason to prefer the bind methods over passing parameters to execute when you don't have to take advantage of the special behaviors of the former?
You might find bindParam used when you just want to bind a variable reference to a parameter in the query, but perhaps still need to do some manipulations on it and only want the value of the variable calculated at time of query execution. It also allows you to do more complex things like bind a parameter to a stored procedure call and have the returned value updated into the bound variable.
For more, see the bindParam documentation, bindValue documentation and execute documentation.
For example
$col1 = 'some_value';
$pdo->bindParam(':col1', $col1);
$col1 = 'some_other_value';
$pdo->execute(); // would use 'some_other_value' for ':col1' parameter
bindValue and passing an array to execute behave in much the same way as the parameter value is fixed at that point and SQL executed accordingly.
Following the same example above, but using bindValue
$col1 = 'some_value';
$pdo->bindValue(':col1', $col1);
$col1 = 'some_other_value';
$pdo->execute(); // would use 'some_value' for ':col1' parameter
When passing values directly in execute all values are treated as strings (even if integer value is provided). So if you need to enforce data types, you should always use bindValue or bindParam.
I think you might see bind* used more than execute(array) as many consider it to be better coding practice to explicitly define data types in parameter declarations.
By passing the parameters along with the $pdo->execute() method, all values in the array with be passed, as PDO::PARAM_STR to the statement with the $pdo->bindParam() function.
The main difference that I can see now, is that with the $pdo->bindParam() function, you can define the data type passed along, using the PDO::PARAM_* constants as described in the PHP.net manual
Simple,
the value of bindParam may change but the value of bindValue can not change.
Example:
$someVal=10;
$someVal2=20;
/* In bindParam, the value argument is not bound and
will be changed if we change its value before execute.
*/
$ref->bindParam(':someCol',$someVal);
$someVal=$someVal2;
$ref->execute();
//someCol=20
/* In bindValue, the value argument is bound and
never changed if we change its value before execute.
*/
$ref->bindValue(':someCol',$someVal);
// here assignment is referral (&$someVal)
$someVal=$someVal2;
$ref->execute();
//someCol=10

Dyamically set the PARAM Type for PDO

I have a loop that allocates values to all params set within a bind param. My problem is I'm not quite sure how to dynamically set the param type when I bind them.
For instance, here is the loop:
foreach(array_combine($cols,$vals) as $col => $val) {
$f->bindParam(':'.$col,$val,PDO::PARAM_INT); // loop through columns and values array and bind those params
}
however - if $vals contains a string for one of the values in the array, this breaks (obviously).
How do I set the PARAM_INT dynamically depending on the type of value in $vals?
I've considered using gettype() but that seemed like it would be messy and ugly... :)
Don't bother with binding at all - just send everything right into execute:
$pdo->prepare($sql)->execute(array_combine($cols,$vals));
Don't forget to turn emulation mode off though, as otherwise this method will choke on LIMIT clause parameters.
however, keep in mind that such a dynamical query building you are trying to implement is prone to SQL injection and apply the the appropriate protection.

Is there any way to get the parameters and their order of a stored proc with PDO?

Even with naming the params, using "bindParam" requires that I know the order parameters should be in when calling a stored procedure.
Is there any way to either:
call a stored procedure and during busilding the statement, not have to know the order of the parameters
or get the name and order of the parameters needed for the stored proc from the statement or PDO object?
Why not bind parameters by name?
$stmt = $pdo->prepare("SELECT * FROM mytable WHERE n = :num AND z = :zone");
$stmt->execute(array( "zone" => $zone, "num" => $num ));
By the way, I prefer to pass parameters simply by passing an array to execute(). It's not necessary to use bindParam(), and no benefit to doing so. There's the parameter type specifiers, but if you read the PDO code, these are ignored, at least in the PDO_MySQL driver.
Re your comment: Okay, now I understand your question.
No, there is no way to query a MySQL stored proc to know what parameters it expects, or how you will use them inside the proc. You have to know your own code at least that much.

Should I define my SQL statement statement handle using separate variables in PHP?

Are all 3 options the same (Y/N) or is one better (A/B/C)?
Option A - (1) defining the SQL string in the variable $sql and (2) define the statement handle using the "method" prepare on the variable $sql to compose the statement and (3) activating composition of the statement in step 2 using the execute function.
$sql = "SELECT * FROM table1";
$sth = $dbh->prepare($sql);
$sth->execute();
Option B - Similar to Option C because the ->query method is used directly on the db object and similar to Option A in that the sql statement is kept separate.
$sql = "SELECT * FROM table1";
$sth = $dbh->query($sql);
Option C - The statement handle is the sql query itself (no reference to any another variables and just using one method.
$sth = $dbh->query("SELECT * FROM table1");
Questions:
Do both options yield the same result?
If they yield the same result, is one approach recommended (i.e. best practice)?
Did I get the vocabulary like "variable", "method", and "function" correct?
Does Option A still query the db despite not explicitly using the ->query() method?
What are the pros/cons of including the sql stmnt in a seperate variable vs in the PDO Statement?
I would say both methods are the same about using a string variable or direct text string.
Assuming you using PDO there is difference between prepare statement and invoke a query statement.
In case A, the prepare statement will make the database create a plan so that statement can be reexecuted without reparsing the query string.
In case B the query is executed at once.
In your given example case B would run a little bit faster.
But if your statement uses arguments case A would benefit you with additional security due to placeholders been replaced by the driver.
Do both options yield the same result?
Yes.
If they yield the same result, is one approach recommended (i.e. best practice)?
Both are fine. In your particular example Option B gets the same job done with less code.
However, if you need to use parameters and/or constraints in your query (e.g. ...WHERE id = :id) you need to opt for option A to bind params using the $dbh->bindParam(':id', $id, PDO::PARAM_INT) method after your prepare your statement, e.g:
$dbh->prepare('UPDATE table SET column = :value WHERE id = :id');
$dbh->bindParam(':value', $someNewValue, PDO::PARAM_STR);
$dbh->bindParam(':id', $targetId, PDO::PARAM_INT);
$dbh->execute();
Doing it this way will also protect you from nasty things like SQL injections.
Storing the query in a separate variable is only needed if you plan to re-use that query at a later time in your code. Otherwise you might as well just type it within your prepare/query method directly.
Did I get the vocabulary like "variable", "method", and "function" correct?
Looks about right! Except: "the execute function" is a method. Functions and methods are basically the same things except when they belong to an object they are referred to as methods. In your example execute belongs to the $sth object, so it's called a method.
Does Option A still query the db despite not explicitly using the ->query() method?
Yes. The execute method executes the query that was prepared in $dbh->prepare(...). If you want to use parameters you can call ->bindParam() between your prepare and execute methods. If you don't need parameters, invoking ->query() directly is really the more convenient way to do it.

PDO execution and bindparam

If i do this:
$qry->execute(array($usuario,$pass));
instead of this:
$qry->bindParam(1, $usuario);
$qry->bindParam(2, $pass);
$qry->execute();
does this give a security problem?
Nope, they are semantically identical
And it's specified in the documentation
Execute the prepared statement. If the prepared statement included parameter markers, you must either:
call PDOStatement::bindParam() to bind PHP variables to the parameter markers: bound variables pass their value as input and receive the output value, if any, of their associated parameter markers
or pass an array of input-only parameter values
No, it will not. It will work fine.

Categories