Theres's a similar question here, but actually that doesn't give me the answer:
PHP + PDO: Bind null if param is empty
I need my statement work in a loop, with only changing the binded variables.
Like:
$this->array = array(
"cell1" => "",
"cell2" => "",
);
$this->sth = $db->prepare("INSERT INTO `table`
(`coloumn1`, `coloumn2`)
VALUES (:coloumn1, :coloumn2)");
$this->sth->bindParam(:coloumn1, $this->array['cell1'], PDO::PARAM_STR);
$this->sth->bindParam(:coloumn2, $this->array['cell2'], PDO::PARAM_STR);
//Data proccessing...
foreach($data as $value){
$this->array['cell1'] = $value['cell1'];
$this->array['cell2'] = $value['cell2'];
try {
this->sth->execute();
print_r($this->sth->errorInfo());
}
catch(PDOException $e){
echo 'sh*t!';
}
}
Everything works well until either of the values is an empty string.
My problem is when 'cell1' is an empty string, the bound parameter is a nullreference, and it won't work. But I need the referenced binding because of the loop, so bindValue isn't a solution.
And I need the loop very bad, because of the huge data I want to process.
Any suggestion?
I tried right before execute:
foreach($this->array as $value){
if(!$value) {
$value = "";
}
}
It doesn't work.
The only way that solved my problem is modifying to this:
$this->array['cell1'] = !empty($value['cell1']) ? $value['cell1'] : "";
$this->array['cell2'] = !empty($value['cell2']) ? $value['cell2'] : "";
But this seems too rubbishy...
I know its necroposting, but maybe will help to someone.
You trying to check if the variable false, but not null. And not reapplying values back to array.
foreach($this->array as $value){
if(!$value) {
$value = "";
}
}
Try to check for null in loop
foreach($this->array as $index => $value)
{
$this->array[$index] = !empty($value) ? $value : '';
}
Your question has nothing to do with PDO but with basic PHP.
When there is no variable available - you can't use it at all. So, you have to create it somehow. The way you are using at the moment is not "rubbishy" but quite acceptable. I'd rather call whole code "rubbishy" as it's twice as big as as it should be.
But I need the referenced binding because of the loop, so bindValue isn't a solution.
This assumption is wrong too. Why do you think you can't use bind by value?
$sql = "INSERT INTO `table` (`coloumn1`, `coloumn2`) VALUES (?, ?)";
$sth = $db->prepare($sql);
foreach($data as $value)
{
$value['cell1'] = !empty($value['cell1']) ? $value['cell1'] : "";
$value['cell2'] = !empty($value['cell2']) ? $value['cell2'] : "";
$sth->execute($value);
}
as simple as this
And I need the loop very bad, because of the huge data I want to process.
I don't think it's really huge, as it fits for the PHP process memory. However, consider to use LOAD DATA INFILE query for the real huge amounts.
Related
For many queries, it's faster and easier to just use the question-mark notation for a query. There are various guides and posts about getting the final run query by extending PDO, but I never see one that works when using the question-mark notation. Can this be done? I'm running a query that appears by all accounts to work, but it's not returning results in the actual PDO code for some reason. What does it take to actually get the EXACT final query that PDO is running so I can see where the error is?
$sth = $dbh->prepare("SELECT fromID,toID,m_key FROM messages WHERE (fromID = ? AND toID IN (?)) OR (toID = ? AND fromID IN (?)) AND message LIKE 'addfriend'");
$sth->execute(array($_SESSION['userID'],$include,$_SESSION['userID'],$include));
The problem is not with the use of the ? placeholder, but the fact that you try to bind a single variable to represent a list of variables in the in operator. You have to provide as many ? placeholders in the in operator separated by commas as the number of parameters you want to have there and you need to bind to each placeholder separately.
...fromID IN (?, ?, ?, ..., ?)...
The below method will help you to substitute the value ($params) against ? or :param placeholder. So that we can see the exact query to be executed.
Note: It is useful only for development debugging purpose.
public static function interpolateQuery($query, $params) {
$keys = array();
$values = $params;
# build a regular expression for each parameter
foreach ($params as $key => $value) {
if (is_string($key)) {
$keys[] = '/:'.$key.'/';
} else {
$keys[] = '/[?]/';
}
if (is_array($value))
$values[$key] = implode(',', $value);
if (is_null($value))
$values[$key] = 'NULL';
}
// Walk the array to see if we can add single-quotes to strings
array_walk($values, create_function('&$v, $k', 'if (!is_numeric($v) && $v!="NULL") $v = "\'".$v."\'";'));
$query = preg_replace($keys, $values, $query, 1, $count);
return $query;
}
I have form with lot of inputs, and I'm trying to import them in database (mysql).
I want to use bind but trying to avoid writing all variables so many times. Probably I can't explain so good, so I will here is a code
if(isset($_POST['firstName']) && isset($_POST['lastName']) && isset($_POST['gender'])){
$firstName=trim($_POST['firstName']);
$lastName=trim($_POST['lastName']);
$gender=trim($_POST['gender']);
if(!empty($firstName)&& !empty($lastName)) {
$unos = $db->prepare("INSERT INTO members (firstName,lastName,gender) VALUES (?,?,?)");
$unos->bind_param('sss', $firstName, $lastName, $gender);
if($unos->execute()) {....
1.Well this is working fine , and it's not a problem, but now I want to add more inputs so I tried this
if(isset($_POST['firstName']) && isset($_POST['lastName']) && isset($_POST['gender'])){
$firstName=trim($_POST['firstName']);
$lastName=trim($_POST['lastName']);
$gender=trim($_POST['gender']);
$param=array('$firstName','$lastName','$gender');
$type='sss';
$param_list = implode(',', $param);
if(!empty($param)) {
$unos = $db->prepare("INSERT INTO members (firstName,lastName,gender) VALUES (?,?,?)");
$unos->bind_param($type,implode(',', $param));
if($unos->execute()) {....
and it's not working. I get "Number of elements in type definition string doesn't match number of bind variables"...
I don't get it, because when I echo this implode thing I get what I need.
I'm pretty newbie with PHP, so help will be so precious. :)
You can try this:
if(isset($_POST['firstName']) && isset($_POST['lastName']) && isset($_POST['gender'])){
$firstName=trim($_POST['firstName']);
$lastName=trim($_POST['lastName']);
$gender=trim($_POST['gender']);
$param=array('firstName' => 's','lastName' => 's','gender' => 's');
if(!empty($param)) {
$unos = $db->prepare("INSERT INTO members (". implode(',', array_keys($param) .") VALUES (". implode(',', array_fill(0, count($param), '?')) .")");
foreach($param as $paramName => $paramType) {
$unos->bind_param($paramType, $paramName);
}
if($unos->execute()) {....
You can pus as many parameters to $param array. Key should the name of the db column, value is its type.
You will need a variable for each question mark, but you will also need to bind each of the parameters separately. In your current situation, you bind a comma-separated list of values as a single string parameter.
What about this? I attempted to make the entire code rely on a single array of fields. If you want extra fields, you can just add them to the array and the rest of the code should respond to it. I don't have a proper test environment at hand and I typed this code by heart, so sorry for any typos. :)
// The fixes list of allowed/expected fields. Other values are ignored.
$fields = array('firstname', 'lastname', 'gender');
// Check if each value exists, and put them in an array.
$paramvalues = array();
foreach ($fields as $field) do
{
if (!isset($_POST[$field]))
die("missing field $field");
$paramvalues[] = & $_POST[$field]; // Bind_param wants a ref value, hence `&`
}
// Build a list of fields for the dynamic query.
$fieldlist = implode($fields, ',');
// And a list of placeholders.
$paramlist = implode(array_fill(0, count($fields), '?'), ',');
// And a list of types, assuming all parameters are strings.
$paramtypes = str_pad('', count($fields), 's');
// Prepare the query
$unos = $db->prepare("INSERT INTO members ($fieldlist) VALUES ($paramlist)");
// Build an array of reference values to be passed to call_user_func_array:
$paramrefvalues = array();
$paramrefvalues[] = $paramtypes
foreach ($paramvalues as $value) do
{
$paramrefvalues[] = & $value;
}
// Call bind_param using this array of by-ref parameters
call_user_func_array(array($unos, 'bind_param'), $paramrefvalues);
This code is loosely based on this article
So thanks to suggestions from users here I have started porting my code over to PDO. Everything was going well until one little issue.
I have a small function to handle my database calls, which basically generates the SQL query, does the $dbh->prepare ($sql), then loops through and binds the values, then executes the query.
$sth = $dbh->prepare ($sql);
// bind parameters
if ($action == 'insert' || $action == 'update') {
reset ($array);
foreach ($array as $key => &$value) {
if ($value != 'NOW()') {
$sth->bindParam (':' . $key, $value);
}
}
}
$sth->execute();
This works fine until I need to insert a value of '0'. No errors are returned, but the value that is inserted into the db turns out to be the maximum value for the column type in the table, in this case is "137".
I'd prefer if someone could explain what is happening as well as providing a solution rather than just give me a fix so I can better understand this.
Cheers,
Luke
You're not binding the parameters correctly, check out the manual.
You should use:
$sth->bindParam (':' . $value, [PARAM TYPE - example: PDO::PARAM_INT]);
Below is a function designed to handle a search scenario for a custom class.
I've already tripped over the fact that PDO defaults to binding parameters as strings, causing an integer->string conversion even if it's not appropriate. As you'll see, I corrected that by manually checking if the type is integer and then forcing the use of int in those cases. Problem is, my solution only works for a 'start' value of 0 -- anything higher errors out, and I don't know why. If I manually set the start/count values to their appropriate values ( i. e. instead of :count I use {$count}), everything works fine, so it looks like the binding is still messing up.
How? Or if I'm wrong... what is right?
/*Query is:
SELECT tutor_school.id
FROM tutor_school, tutor_states
WHERE tutor_states.stateName=:state AND tutor_states.id=tutor_school.state
GROUP BY tutor_school.id order by tutor_school.name asc
LIMIT :start, :count*/
$db = Database::get_user_db();
$statement = $db->prepare($query);
foreach ($executeArray as $key => $value)
{
if (getType($value) == 'integer')
{
$statement->bindParam($key, $executeArray[$key], PDO::PARAM_INT);
}
else
{
$statement->bindParam($key, $value);
}
}
var_dump($executeArray);//count and start are still ints
if ($statement->execute())
{
var_dump($executeArray);//start and count are now strings
var_dump($statement->errorInfo());
var_dump($query);
$values = $statement->fetchAll();
$return = array();
foreach ($values as $row)
{
$school = School::schoolWithId($row[0]);
if (!empty($school))
{
$return[] = $school;
}
}
return $return;
}
Metadata (such as the LIMIT arguments) can't be parametrized. You will have to use (properly sanitized) interpolation instead.
I'm trying to do a little PDO CRUD to learn some PDO. I have a question about bindParam. Here's my update method right now:
public static function update($conditions = array(), $data = array(), $table = '')
{
self::instance();
// Late static bindings (PHP 5.3)
$table = ($table === '') ? self::table() : $table;
// Check which data array we want to use
$values = (empty($data)) ? self::$_fields : $data;
$sql = "UPDATE $table SET ";
foreach ($values as $f => $v)
{
$sql .= "$f = ?, ";
}
// let's build the conditions
self::build_conditions($conditions);
// fix our WHERE, AND, OR, LIKE conditions
$extra = self::$condition_string;
// querystring
$sql = rtrim($sql, ', ') . $extra;
// let's merge the arrays into on
$v_val = array_values($values);
$c_val = array_values($conditions);
$array = array_merge($v_val, self::$condition_array);
$stmt = self::$db->prepare($sql);
return $stmt->execute($array);
}
in my "self::$condition_array" I get all the right values from the ?. SO the query looks like this:
UPDATE table SET this = ?, another = ? WHERE title = ? AND time = ?
as you can see I dont use bindParams instead I pass the right values in the right order ($array) directly into the execute($array) method. This works like a charm BUT is it safe not use use bindParam here?
If not then how can I do it?
Thanks from Sweden
Tobias
Yes, it is safe. bindParam() associates a parameter with a variable, use it when you want value of a variable to be used when execute() is called. Otherwise what you are doing is fine.
PHP Docs on PDO bindParam()