JSON Database update loosing key values - php

I got this in my DB (23 is my picture ID):
{"23" : {"13x18":"5","20X30":"5","30x45":"4","digital":"4"}}
I want to add another data just like this one in the same spot so it would look like this :
["23" : {"13x18":"5","20X30":"5","30x45":"4","digital":"4"},
"42" : {"13x18":"2","20X30":"1","30x45":"3","digital":"1"}]
Here is the code is use :
$clientChoice = [];
$clientChoice[$post['picId']] = $test;
$select = (new GalleryCategoriesModel)->findByUrl($post['url']);
if($select['clientChoice'] != null){
$tabs = json_decode($select['clientChoice'], true);
$new = array_merge($tabs, $clientChoice);
$chosen = json_encode($new);
} else {
$chosen = json_encode($clientChoice);
}
$update = (new GalleryCategoriesModel)->update(['clientChoice'=>$chosen], $post['id']);
And here is the result i got with it :
[{"13x18":"5","20X30":"5","30x45":"4","digital":"4"},
{"13x18":"2","20X30":"1","30x45":"3","digital":"1"}]
What am I missing or doing wrong?
----------------- CORRECTION ------------------
Thanks to the answer given, here is what i do now :
$clientChoice = [];
$clientChoice[$post['picId']] = $test;
$select = (new GalleryCategoriesModel)->findByUrl($post['url']);
if($select['clientChoice'] != null){
$tabs = json_decode($select['clientChoice'], true);
$new = $tabs + $clientChoice;
$chosen = json_encode($new);
} else {
$chosen = json_encode($clientChoice);
}
$update = (new GalleryCategoriesModel)->update(['clientChoice'=>$chosen], $post['id']);
And here is what I got in my DB :
{"25":{"13x18":"1","20X30":"3","30x45":"5","digital":"1"},
"37":{"13x18":"4","20X30":"8","30x45":"3","digital":"2"}}

Your issue is with your call to array_merge. From the manual:
Values in the input arrays with numeric keys will be renumbered with incrementing keys starting from zero in the result array
So your two arrays that have keys of 23 and 42 end up merged as:
Array
(
[0] => Array
(
[13x18] => 5
[20X30] => 5
[30x45] => 4
[digital] => 4
)
[1] => Array
(
[13x18] => 2
[20X30] => 1
[30x45] => 3
[digital] => 1
)
)
You can work around this by using the array union operator (+), which will preserve the keys from both arrays (although it will ignore $clientChoice if the key is the same as one already existing in $tabs), however since they are id values I assume this should not occur.
$new = $tabs + $clientChoice;
In this case, $new contains:
Array
(
[23] => Array
(
[13x18] => 5
[20X30] => 5
[30x45] => 4
[digital] => 4
)
[42] => Array
(
[13x18] => 2
[20X30] => 1
[30x45] => 3
[digital] => 1
)
)
Demo on 3v4l.org

Related

Create array batch based on similar array key

I am trying to create an batch of similar array's based on first key of array.
Here is the input array
$headers = array(
0 => 'order_number',
1 => 'product_sku',
);
$input_array = array (
0 =>
array (
0 => '311000000706',
1 => 'S503053'
),
1 =>
array (
0 => '311000000706',
1 => 'S516135'
),
2 =>
array (
0 => '311000000703',
1 => 'S526587'
),
3 =>
array (
0 => '311000000703',
1 => 'S526587'
),
);
I am trying to create an seperate array if it has same order id like if two array has same order id = "311000000706"
then desired output will be
$desired_output = array (
0 =>
array (
0 => '311000000706',
1 => 'S503053'
),
1 =>
array (
0 => '311000000706',
1 => 'S516135'
));
Here is what i have tried
$prev_order_id_s = null;
$similar_order_ids = array();
foreach ($input_array as $key => $level):
if ($level['0'] == $prev_order_id_s) {
$similar_order_ids[][] = $level;
}
$prev_order_id_s = $level['0'];
endforeach;
but i am not getting desired output, i need some advice on this.
can you please advice some logic on this ?
Here is the compiler with above code - paiza.io/projects/fB-8CfiEuTX1cJXnXAZS3g
Instead of maintaining variables for previous order IDs, I would rather suggest you to take advantage of order ID as an associative key and keep adding rows to it whenever you find a matching order ID. In the end, you could array_values() on the collected data to remove order IDs as keys.
<?php
$set = [];
foreach($input_array as $row){
$set[$row[0]][] = $row;
}
$result = array_values($set);
print_r($result);
Do not use foreach to filter your array. You can use the array_filter function in PHP. Let's assume you want to check the first element of each array (means the zero index) and your desired value for this key is '311000000706'. It transaltes to PHP like this:
$desired_output= array_filter($input_array, function ($value) {
return $value[0] === '311000000706';
});

Store array of arrays value in one comma separated string [duplicate]

This question already has answers here:
Implode a column of values from a two dimensional array [duplicate]
(3 answers)
Closed 7 months ago.
I have this return array
$leaseArray = Array ( [0] => Array ( [LeaseNumber] => OL/2011/0343 ) [1] => Array ( [LeaseNumber] => 184 ) [2] => Array ( [LeaseNumber] => OL/2011/0118 ) [3] => Array ( [LeaseNumber] => OL/2016/1759 ) [4] => Array ( [LeaseNumber] => OL/2013/0858 ) [5] => Array ( [LeaseNumber] => OL/2012/0535 ) [6] => Array ( [LeaseNumber] => OL/2017/2208 ) [7] => Array ( [LeaseNumber] => 2355 ) )
I want to save all the values of LeaseNumber in to one comma separated string
like $string = "OL/2011/0343 , 184 , OL/2011/0118 , OL/2016/1759"
please help me
$lease = array();
for($i=0;$i<=count($leaseArray); $i++){
$lease = $leaseArray[$i]['LeaseNumber'];
}
If you want a one-liner then this is the way
$csv = implode(' , ', array_column($a, 'LeaseNumber'));
As I said in the comments, 1 line, 2 function calls.
If you want a one-liner then this could work:
$csv = implode( ' , ', array_map( function( $a ){ return $a[ 'LeaseNumber' ]; }, $leaseArray ) );
expanded:
$csv = implode( ' , ', // step 2: implode on ' , ': space-comma-space
array_map( // step 1: pass $lease array into array_map so that we can get a new array
function( $a ){ return $a[ 'LeaseNumber' ]; }, // Accept each array in $a and only return the LeaseNumber. array_map will build a new array out of just these values
$leaseArray // the array to be processed
)
);
In essence, this is the same as:
$csv = implode( ' , ', array_column( $a, 'LeaseNumber' ) );
but array_map() allows you to transform the data before output/return if you need to.
One-liners are great but sometimes hard to read. If you want to stick with what you have here are some note
<?php
$array = array(array("LeaseNumber" => "OL/2011/0343"), array("LeaseNumber"=> 184 ), array("LeaseNumber"=> "OL/2011/0118") , array("LeaseNumber"=> "OL/2016/1759"), array("LeaseNumber"=> "OL/2013/0858"), array("LeaseNumber"=> "OL/2012/0535"), array("LeaseNumber"=> "OL/2017/2208"), array("LeaseNumber"=> 2355));
$lease = array();
//Not equal to the count it starts at 1 not 0
for($i=0;$i<count($array); $i++){
//lease is an array add to the index not overwrite
$lease[] = $array[$i]['LeaseNumber'];
}
//You needed to finish with this
$csv = implode(", ",$lease);
echo $csv;
As an fyi switch to a foreach in this case makes life easier:
$lease = array();
foreach($array as $obj){
$lease[] = $obj["LeaseNumber"];
}

Looping through array and get non-repeating values

I have an array of elements which I queried from the mongoDB.
This array has the id of a device and value of this device's consumptions.
For example there are 3 different ids -> 18,5,3 and multiple mixed values.
// first record of 18 so get value.
$row[0]["id"] = 18;
$row[0]["value"] = 100;
// not first record of 18 so ignore and move to the next record
$row[1]["id"] = 18;
$row[1]["value"] = 40;
// first record of 5 so get value.
$row[2]["id"] = 5;
$row[2]["value"] = 20;
// not first record of 18 so ignore and move to the next record
$row[3]["id"] = 18;
$row[3]["value"] = 30;
// first record of 3 so get value.
$row[4]["id"] = 3;
$row[4]["value"] = 20;
//not first record of 5 so ignore and move to the next record**
$row[5]["id"] = 5;
$row[5]["value"] = 30;
// not first record of 18 so ignore and move to the next record
$row[6]["id"] = 18;
$row[6]["value"] = 10;
...
....
What I am trying to do is loop through this $row array and get the most recent value of the id.
For example in above example what I want to return is:
id value
18 100
5 20
3 20
How can I do that kind of logic?
It can be done in several ways. The easiest one is to use a foreach:
$result = array();
foreach ($row as $i) {
if (! array_key_exists($i['id'], $result)) {
$result[$i['id']] = $i['value'];
}
}
# Verify the result
print_r($result);
The output is:
Array
(
[18] => 100
[5] => 20
[3] => 20
)
The same processing, but using array_reduce():
$result = array_reduce(
$row,
function(array $c, array $i) {
if (! array_key_exists($i['id'], $c)) {
$c[$i['id']] = $i['value'];
}
return $c;
},
array()
);
If you want to keep only the first occurrence of each 'id' then just add the values to an aggregate array - but only if they haven't been added already. Then grab the values of the aggregate array.
https://tehplayground.com/NRvw9uJF615oeh6C - press Ctrl+Enter to run
$results = array();
foreach ($row as $r) {
$id = $r['id'];
if (! array_key_exists($id, $results)) {
$results[$id] = $r;
}
}
$results = array_values($results);
print_r($results);
Array
(
[0] => Array
(
[id] => 18
[value] => 100
)
[1] => Array
(
[id] => 5
[value] => 20
)
[2] => Array
(
[id] => 3
[value] => 20
)
)
Try this
$alreadyfound = []; // empty array
$result = [];
foreach ($row as $item)
{
if (in_array($item["id"], $alreadyfound))
continue;
$alreadyfound[] = $item["id"]; // add to array
$result[] = $item;
}
The result
Array
(
[0] => Array
(
[id] => 18
[value] => 100
)
[1] => Array
(
[id] => 5
[value] => 20
)
[2] => Array
(
[id] => 3
[value] => 20
)
)
The array_unique() function is exactly what you are looking at.
See the documentation here : array_unique() documentation
Using array_column with an index key will almost do it, but it will be in the reverse order, so you can reverse the input so that it works.
$result = array_column(array_reverse($row), 'value', 'id');

PHP Unique Values from Column in Array

I have an array that is generated from a SQL query that I run. It looks like the following:
$arr[$i]['id'] = $id;
$arr[$i]['name'] = $name;
$arr[$i]['email'] = $email;
How can I get the unique values from the email column? I appreciate the help.
The best answer is :
array_unique(array_column($arr, 'email'))
Either filter it in your column using the DISTINCT method in MySQL, or use something like
$uniqueEmails = array();
foreach($arr as $array)
{
if(!in_array($array['email'], $uniqueEmails)
$uniqueEmails[] = $array['email'];
}
Since PHP 5.5, a new function called array_column() is also available.
You can use it following way:
$allEmails = array_column($arr, 'email');
$uniqueEmails = array_unique($allEmails);
Remove duplicates from array comparing a specific key
Consider the same array but id of 3rd index is different:
$all_array = Array
(
[0] => Array
(
[id] => 1
[value] => 111
)
[1] => Array
(
[id] => 2
[value] => 222
)
[2] => Array
(
[id] => 3
[value] => 333
)
[3] => Array
(
[id] => 4
[value] => 111
)
)
Now, both 1 & 4 have same values. So we want to remove any of them:
$unique_arr = array_unique( array_column( $all_array , 'value' ) );
print_r( array_intersect_key( $all_array, $unique_arr ) );
If you get the list sorted by email from SQL you can improve performance by looping through the array like Gareth does, but instead only compare current email address with the last inserted email address. Below is a code example for this:
$uniqueEmails = array();
$lastemail = '';
foreach($arr as $array)
{
if($array['email'] != $lastemail)
{
$uniqueEmails[] = $array['email'];
$lastemail = $array['email'];
}
}

parsing out the last number of the post

Ok so i have a post that looks kind of this
[optional_premium_1] => Array
(
[0] => 61
)
[optional_premium_2] => Array
(
[0] => 55
)
[optional_premium_3] => Array
(
[0] => 55
)
[premium_1] => Array
(
[0] => 33
)
[premium_2] => Array
(
[0] => 36 )
[premium_3] => Array
(
[0] => 88 )
[premium_4] => Array
(
[0] => 51
)
how do i get the highest number out of the that. So for example, the optional "optional_premium_" highest is 3 and the "premium_" optional the highest is 4. How do i find the highest in this $_POST
You could use array_key_exists(), perhaps something like this:
function getHighest($variableNamePrefix, array $arrayToCheck) {
$continue = true;
$highest = 0;
while($continue) {
if (!array_key_exists($variableNamePrefix . "_" . ($highest + 1) , $arrayToCheck)) {
$continue = false;
} else {
highest++;
}
}
//If 0 is returned than nothing was set for $variableNamePrefix
return $highest;
}
$highestOptionalPremium = getHighest('optional_premium', $_POST);
$highestPremium = getHighest('premium', $_POST);
I have 1 question with 2 parts before I answer, and that is why are you using embedded arrays? Your post would be much simpler if you used a standard notation like:
$_POST['form_input_name'] = 'whatever';
unless you are specifically building this post with arrays for some reason. That way you could use the array key as the variable name and the array value normally.
So given:
$arr = array(
"optional_premium_1" => "61"
"optional_premium_2" => "55"
);
you could use
$key = array_keys($arr);
//gets the keys for that array
//then loop through get raw values
foreach($key as $val){
str_replace("optional_premium_", '', $val);
}
//then loop through again to compare each one
$highest = 0;
for each($key as $val){
if ((int)$val > $highest) $highest = (int)$val;
}
that should get you the highest one, but then you have to go back and compare them to do whatever your end plan for it was.
You could also break those into 2 separate arrays and assuming they are added in order just use end() http://php.net/manual/en/function.end.php
Loop through all POST array elements, pick out elements having key names matching "name_number" pattern and save the ones having the largest number portion of the key names. Here is a PHP script which does it:
<?php // test.php 20110428_0900
// Build temporary array to simulate $_POST
$TEMP_POST = array(
"optional_premium_1" => array(61),
"optional_premium_2" => array(55),
"optional_premium_3" => array(55),
"premium_1" => array(33),
"premium_2" => array(36),
"premium_3" => array(88),
"premium_4" => array(51),
);
$names = array(); // Array of POST variable names
// loop through all POST array elements
foreach ($TEMP_POST as $k => $v) {
// Process only elements with names matching "word_number" pattern.
if (preg_match('/^(\w+)_(\d+)$/', $k, $m)) {
$name = $m[1];
$number = (int)$m[2];
if (!isset($names[$name]))
{ // Add new POST var key name to names array
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
} elseif ($number > $names[$name]['max_num'])
{ // New largest number in key name.
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
}
}
}
print_r($names);
?>
Here is the output from the script:
Array
(
[optional_premium] => Array
(
[name] => optional_premium
[max_num] => 3
[key_name] => optional_premium_3
[value] => Array
(
[0] => 55
)
)
[premium] => Array
(
[name] => premium
[max_num] => 4
[key_name] => premium_4
[value] => Array
(
[0] => 51
)
)
)
Though ineffective, you could try something like
$largest = 0;
foreach($_POST as $key => $value)
{
$len = strlen("optional_premium_");
$num = substr($key, $len);
if($num > $largest)
$largest = $num;
}
print_r($largest);
The problem being that this will only work for one set of categories. It will most likely give errors throughout the script.
Ideally, you would want to reorganize your post, make each array be something like
[optional_premium_1] => Array
(
[0] => 61
["key"] => 1
)
[optional_premium_2] => Array
(
[0] => 61
["key"] => 2
)
Then just foreach and use $array["key"] to search.

Categories