0

I´m sending a javascript object through ajax with this structruce

[
  {  name:'box', price:'20', id:'72', units : 2 },
  {  name:'box2', price:'30', id:'73', units : 2 },
  {  name:'box3', price:'40', id:'74', units : 2 }
]

Getting the data on the server this way

$data = json_decode(file_get_contents("php://input"),true);
$queryconst = '';
foreach($data as $key => $value){
    $format[$key] = $value;
    $format_keys = array_keys($format[$key]);
    $newArray = $this->slashesToArray($value);
    $queryconst = $queryconst.'(\''.implode("','", $newArray).'\'),';           
}
$queryconst = rtrim($queryconst, ",");
$query = "INSERT INTO format (".implode(",", $format_keys).") VALUES ".$queryconst;

If the data that i`m sending has a single object

[
  {  name:'box', price:'20', id:'72', units : 2 }
]

everything works fine

$query = INSERT INTO format (name,units,price,id) VALUES ('box','2','20','72')

the problem comes when the data has more than one object

[
  {  name:'box', price:'20', id:'72', units : 2 },
  {  name:'box2', price:'30', id:'73', units : 2 },
  {  name:'box3', price:'40', id:'74', units : 2 }
]

and the query

$query = INSERT INTO format (price,name,units,product_id) 
         VALUES ('box','2','20','74'),('30','box2','2','74'),('40','box3','2','74')

the order fo the first object is different from the rest and the query fails

Any clue?

2 Answers 2

1

Finally I've fixed it, just ordering the array at the begining of the loop

$data = json_decode(file_get_contents("php://input"),true);
$queryconst = '';
foreach($data as $key => $value){
    ksort($value);
    $format[$key] = $value;
    $format_keys = array_keys($format[$key]);
    $newArray = $this->slashesToArray($value);
    $queryconst = $queryconst.'(\''.implode("','", $newArray).'\'),';           
}
$queryconst = rtrim($queryconst, ",");
$query = "INSERT INTO format (".implode(",", $format_keys).") VALUES ".$queryconst;
Sign up to request clarification or add additional context in comments.

Comments

0

JSON objects are unordered. Nothing in the spec or any implementation is guaranteeing any particular order when iterating, encoding or decoding JSON objects. You have to use the object key names explicitly instead of implicitly relying on their order.

Something along these lines:

$data = json_decode(file_get_contents("php://input"), true);

// this is your whitelisting against column injection
$allowedColumns = ['name', 'price', ...];
$columns = array_keys($data[0]);
if (array_diff($columns, $allowedColumns)) {
    throw new InvalidArgumentException;
}

$values = [];
foreach ($data as $row) {
    // this maps the values to the column names in the right order, including escaping
    $values[] = array_map(function ($column) use ($row) {
        return sprintf("'%s'", mysql_real_escape_string($row[$column]));
    }, $columns);
}

$query = sprintf(
    'INSERT INTO (%s) VALUES %s',
    join(', ', $columns),
    join(', ', array_map(function ($row) {
        return sprintf('(%s)', join(', ', $row));
    }, $values))
);

Note the use of mysql_real_escape_string for proper escaping. Note also that this is deprecated and your should use PDO or mysqli with placeholders and parameter binding instead.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.