insert values from an object where keys are columnn names - php

I have a json_encoded string where keys are column names and need to insert corresponding values
$str = {"fname":"lorem","sname":"ipsum","nick":"dolor"};
fname sname nick - are column names - and need to insert lorem ipsum dolor
I made an object - $obj = json_decode($str); - but what then?
in a plain example - without the object - it would be like this:
function insert($fname, $sname, $nick){
$sq = "insert into table (fname, sname, nick) values (:afname, :asname, :anick)";
$st = $db->prepare($sq);
$st->execute([
":afname" => $fname, // lorem
":asname" => $sname, // ipsum
":anick" => $nick // dolor
]);
}
how to do this using the given object?

After making object, just pass these in insert method(use your above mentioned insert method)
$obj = json_decode($str);
insert($obj->fname, $obj->sname, $obj->nick);
If you wanna pass as an object in the function, you can do in following manner.
function insert($obj){
$sq = "insert into table (fname, sname, nick) values (:afname, :asname, :anick)";
$st = $db->prepare($sq);
$st->execute([
":afname" => $obj->fname, // lorem
":asname" => $obj->sname, // ipsum
":anick" => $obj->nick // dolor
]);
}
If you want to use dynamically insert columns with their values. You can do so in following manner.
$arr = json_decode($str, true);
$sq = "insert into table (". implode(', ', array_keys($arr)) . ") values (" . implode(',',array_fill(0, count($arr),"?")) . ")";
$st = $db->prepare($sq);
$st->execute(array_values($arr));
Here
implode(', ', array_keys($arr)) - create a comma separated column names based on array keys.
implode(',',array_fill(0, count($arr),"?")) - create ? for prepared statement. Number of ? would be equal to array length and then concatenated with ,.
array_values($arr) pass values as array.

Related

pdo array getting Array to string conversion error

When I run this code it should store ben in the database but, it says Array in the first_name column and it gives the string to conversion error. How would I get rid of the error?
<?php $data = ['first_name' => 'ben'] ?>
<?php $sql = "INSERT INTO names (first_name) values (?);" ?>
<?php $statement = $pdo->prepare($sql); ?>
<?php $statement->execute([$data]); ?>
PDO has two different ways to bind parameters. The first is positional. In this case, the array you pass to execute() should be an indexed array, with values in the same order that you want them to bind to the question marks:
$sql = "INSERT INTO table (col1, col2) values (?, ?)";
$data = ['value for col1', 'value for col2'];
Note the values must be in the same order that they're going to be used:
$data = ['value for col2', 'value for col1']; // This won't work, wrong order!
The alternative (and in my opinion, superior) method is to use named parameters. Here, you need to use an associative array with a key named the same as your parameter placeholder.
$sql = "INSERT INTO table (col1, col2) values (:col1, :col2)";
$data = ['col1' => 'value for col1', 'col2' => 'value for col2'];
The order of these now does not matter because they're keyed by the array name instead of the position:
$data = ['col2' => 'value for col2', 'col1' => 'value for col1']; // Still good!
Your problem (in addition to the extra array wrap that #Sammitch pointed out) is that you have mixed these two techniques together in an incompatible way -- you're using positional parameters, but have provided an associative array. So, in your case, you either need to use positional parameters and an indexed array:
$data = ['ben'];
$sql = "INSERT INTO names (first_name) values (?);";
$statement = $pdo->prepare($sql);
$statement->execute($data);
Or named parameters and an associative array:
$data = ['first_name' => 'ben'];
$sql = "INSERT INTO names (first_name) values (:first_name);";
$statement = $pdo->prepare($sql);
$statement->execute($data);

How storing array values in different columns of table using php

Here is the piece of code so far I've tried:
$month = array('red','green','red');
$values = array();
foreach($month as $dataset)
{
$values[] = ($dataset);
}
$columns = implode(", ",array_keys($values));
$escaped_values = array_values($values);
$valu = implode(", ", $escaped_values);
$sql = "INSERT INTO abc (col1,col2,col3) VALUES ('$valu');";
Here is the output:
Error: INSERT INTO abc (col1,col2,col3) VALUES ('red, green, red');
Column count doesn't match value count at row 1
What I am trying to do is to store values in the array where the value of the array may vary depending upon the value the user gave, and then store it in different columns. For example, if the total columns are 3 and array value is 2 then store values in col1 and col2 and null value in col3.
With the single quotes around the whole string 'red, green, red' that is the value for col1 only.
It should look more like this 'red','green','red'.
So quick fix is this $valu = implode("','", $escaped_values);
Added a single quotes inside your implode.
The outside quotes will be captured in the final statement as detailied in the problem above:
$sql = "INSERT INTO abc (col1,col2,col3) VALUES ('$valu');";
Here the Code after making it work properly
$month = array('red','green','red');
$values = array();
foreach($month as $dataset)
{
$values[] = "'{$dataset}'";
}
$columns = implode(", ",array_keys($values));
$escaped_values = array_values($values);
$valu = implode(", ", $escaped_values);
$sql = "INSERT INTO abc (col1,col2,col3) VALUES ($valu);";
The values are into the single quote. Please check below example.
INSERT INTO abc (col1,col2,col3) VALUES ('red', 'green', 'red');
No one else seems to have addressed the actual issue.
What I am trying to do is to store values in the array where the value
of the array may vary depending upon the value the user gave, and then
store it in different columns. For example, if the total columns are 3
and array value is 2 then store values in col1 and col2 and null value
in col3.
So if the values come in as an array at different lengths, and you want to insert as null or limit to the max length of the columns then you can do it like the following.
Ideally, you want to produce an array which looks like:
$data = [
'col1' => 'red',
'col2' => 'green',
'col3' => null
];
To do that without any looping define the database columns, then create an array of the same length of null values, then slice the input array to the same length and merge, this will produce an array like above.
<?php
$columns = [
'col1',
'col2',
'col3',
];
$month = [
'red',
'green'
];
$data = array_combine(
$columns,
array_slice($month, 0, count($columns))+array_fill(0, count($columns), null)
);
Now you simply need to implode the array into your query, using ? for placeholders for the prepared query.
$sql = '
INSERT INTO abc (
'.implode(', ', array_keys($data)).'
) VALUES (
'.implode(', ', array_fill(0, count($data), '?')).'
)';
Will produce:
INSERT INTO abc (
col1, col2, col3
) VALUES (
?, ?, ?
)
Then just do your query, for example:
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
Simple clean and safe.

How to insert values to table that are there only in the JSON object in PHP

I've a table which is created with below SQL statement
CREATE TABLE example (
col1 varchar(20) DEFAULT NULL,
col2 varchar(20) DEFAULT NULL,
col3 varchar(20) DEFAULT NULL
)
I want to insert values to this table from a JSON object. JSON object is constructed such way that its key is the column name and value is the value to be inserted.
How do I write a PHP code to only insert the values that are there in the JSON object?
For instance, If I have a JSON object
{
"col1": "some value",
"col3": "some value"
}
The insert statement should only insert values to col1 and col3 and the col2 should remain as NULL.
Please help me out to solve this puzzle. PHP with PDO is preferable.
Experiments performed so far
$object = json_decode($jsonObject);
foreach ($object as $col => $val) {
$columns .= $col . ",";
$values .= $val . ",";
}
$sql = "INSERT INTO example (" .substr($columns, 0, strlen($columns)-2) .
") VALUES (" . substr($values, 0, strlen($columns)-2) . ")";
Your code is pretty close. The problem is that you don't have quotes around each value in $values.
Here's another way to write it:
$object = json_decode($jsonObject, true);
$columns = implode(', ', array_keys($object);
$values = implode(', ', array_map(function($x) { return "'$x'"; }, $object));
$sql = "INSERT INTO example($columns) VALUES ($values)";
The function in array_map() returns each value with quotes around it, then implode() combines them all with commas.
If you're using PDO, you can pass an array of values to PDOStatement::execute().
$values = array_values($object);
// Create "?, ?, ?, ..." string with enough placeholders for the values
$placeholders = implode(', ', array_fill(0, count($values), '?'));
$sql = "INSERT INTO example($columns) VALUES ($placeholders)";
$stmt = $pdo->prepare($sql);
$result = $stmt->execute($values);

How to bind multiple params to prepare statement [duplicate]

Is there's an easy way of binding multiple values in PDO without repitition ? Take a look at the following code :
$result_set = $pdo->prepare("INSERT INTO `users` (`username`, `password`, `first_name`, `last_name`) VALUES (:username, :password, :first_name, :last_name)");
$result_set->bindValue(':username', '~user');
$result_set->bindValue(':password', '~pass');
$result_set->bindValue(':first_name', '~John');
$result_set->bindValue(':last_name', '~Doe');
$result_set->execute();
Here, I binded values in a repepeated way which is 4 times. So is there's an easy way of binding multiple values in PDO ?
You can always bind values within the arguments of execute() as long as you're fine with the values being treated as PDO::PARAM_STR (string).
$result_set = $pdo->prepare("INSERT INTO `users` (`username`, `password`, `first_name`, `last_name`) VALUES (:username, :password, :first_name, :last_name)");
$result_set->execute(array(
':username' => '~user',
':password' => '~pass',
':first_name' => '~John',
':last_name' => '~Doe'
));
You can use the array passed just like any array:
$user = "Nile";
$pdo->execute(array(":user" => $user));
If you want to bind based on type (string, int, etc), then no. If you're fine with binding everything as a string:
$stmt = $db->prepare("...");
$stmt->execute(array(
'foo' => 'bar',
'something' => 'else',
'third' => 'thing',
));
To truly never type anything twice, you can use an array to supply the data, and use a function on that same array to output the binding portion of the MySQL query. For example:
function bindFields($fields){
end($fields); $lastField = key($fields);
$bindString = ' ';
foreach($fields as $field => $data){
$bindString .= $field . '=:' . $field;
$bindString .= ($field === $lastField ? ' ' : ',');
}
return $bindString;
}
The data and column names come from a single associative array ($data). Then, use bindFields($data) to generate a string of column = :column pairs to concatenate into the MySQL query:
$data = array(
'a_column_name' => 'column data string',
'another_column_name' => 'another column data string'
);
$query = "INSERT INTO tablename SET" . bindFields($data);
$result = $PDO->prepare($query);
$result->execute($data);
bindFields($data) output:
a_column_name=:a_column_name,another_column_name=:another_column_name

INSERT array - PDO

I've got a portion of code that is supposed to take the data entered in a form, store it in an array and then enter it into the database. I have used var_dump on $fields and $data and they are both returning the information entered in the field (in the add_habbo function). So the problem I've got is that the MYSQL/PDO code isn't inserting this data into the database.
This is the code that I am using to insert them into the database:
$fields = '`' . implode('`, `', array_keys($habbo_data)) . '`';
$data = '\'' . implode('\', \'', $habbo_data) . '\'';
var_dump($fields);
var_dump($data);
global $con;
$query = "INSERT INTO `personnel` (:fields) VALUES (:data)";
$result = $con->prepare($query);
$result->bindParam(':fields', $fields, PDO::PARAM_STR);
$result->bindParam(':data', $data, PDO::PARAM_STR);
$result->execute();
I get the impression it has something to with the bindParam sections, possibly PDO::PARAM_STR? Thanks for your assistance!
Update:
$fields = '`' . implode('`, `', array_keys($habbo_data)) . '`';
$fields_data = ':' . implode(', :', array_keys($habbo_data));
var_dump($fields);
var_dump($fields_data);
global $con;
$query = "INSERT INTO `personnel` (`rank`, `habbo_name`, `rating`, `asts`, `promotion_date`, `transfer_rank_received`, `cnl_trainings`, `rdc_grade`,
`medals`, `branch`) VALUES ({$fields_data})";
$result = $con->prepare($query);
$result->execute($habbo_data);
$arr = $result->errorInfo();
print_r($arr);
Error:
Array ( [0] => 21S01 [1] => 1136 [2] => Column count doesn't match
value count at row 1 )
Prepared statements are not the same as copy and paste!
INSERT INTO `personnel` (:fields) VALUES (:data)
You're telling PDO/MySQL here that you want to insert exactly one piece of data (:data) into one field (:field). The value is one string containing commas, not several values separated by commas.
Furthermore you can only bind data, not structural information like field names. You will have to create a query like so:
INSERT INTO `personnel` (foo, bar, baz) VALUES (?, ?, ?)
and then bind data to the three placeholders separately.
You cannot do that:
You need to add each variable / field-name and value individually;
You can only bind values and not table- or field-names.
Table- and field-names you will have to inject directly into your sql so to prevent sql injection problems, you need to check them against a white-list before doing that.
So in your case that would be something like (rough draft):
// assuming all fields have been checked against a whitelist
// also assuming that the array keys of `$habbo_data` do not contain funny stuff like spaces, etc.
$fields = '`' . implode('`, `', array_keys($habbo_data)) . '`';
$fields_data = ':' . implode(', :', array_keys($habbo_data));
var_dump($fields);
var_dump($fields_data);
global $con;
$query = "INSERT INTO `personnel` ({$fields}) VALUES ({$fields_data})";
$result = $con->prepare($query);
$result->execute($habbo_data);
Note that I am not manually binding the variables any more but sending the associative $habbo_data array directly as a parameter to the execute method, see example #2.

Categories