Hash/array compare and merge - php

I have two data sets.
First:
{
"status": "OK",
"message": "Data Show Successful",
"name0": "Al",
"city": "",
"pree": "R",
"allknife": [
{
"name": "Folder",
"pos": "G",
"pos_le": "",
},
{
"name": "Folder Two",
"pos": "G",
"pos_le": "",
}
]
}
Second:
{
"status": "OK",
"message": "Data Show Successful",
"name0": "",
"city": "",
"pree": "R",
"allknife": [
{
"name": "Folder",
"pos": "",
"pos_le": "R",
},
{
"name": "Folder Two",
"pos": "G",
"pos_le": "",
}
]
}
Now I compare the second data set with the first data set. If any item is empty in the second data set, then I want it to be pulled from first data set.
For instance, in the second hash name0 is empty so the value should be replaced using the value from the first hash. Also the allknife array should use the same logic.
I cant understand how implement it. I am trying with array_merge(), to no avail.

There are a lot of things that might be optimized but I leave it to you!
// Just a simple example
function arfill($example, $input){
foreach($input as $key => $value){
if($value == ""){
// Easy peasy set it
$input[$key] = $example[$key];
}
if(is_array($value)){
// Little recursion here
$input[$key] = arfill($example[$key], $input[$key]);
}
}
return $input;
}

Since you want to replace the value of name0 with the valie that is in array2 you should use
array_replace(array1, array2)

Here is one idea, to remove the empty entries from both arrays ( array_filter_recursive() ) and to use array_replace_recursive().
array_replace_recursive:
array_replace_recursive() replaces the values of array1 with the same
values from all the following arrays. If a key from the first array
exists in the second array, its value will be replaced by the value
from the second array. If the key exists in the second array, and not
the first, it will be created in the first array. If a key only exists
in the first array, it will be left as is. If several arrays are
passed for replacement, they will be processed in order, the later
array overwriting the previous values.
$arr1 = json_decode( $arr1, true );
$arr2 = json_decode( $arr2, true );
function array_filter_recursive( $input ) {
foreach ( $input as &$value ) {
if ( is_array( $value ) )
$value = array_filter_recursive( $value );
}
return array_filter( $input );
}
$arr = array_replace_recursive(
$arr1, $arr2, array_filter_recursive( $arr1 ), array_filter_recursive( $arr2 )
);
print_r( $arr );
/*
Array (
[status] => OK
[message] => Data Show Successful
[name0] => Al
[city] =>
[pree] => R
[allknife] => Array (
[0] => Array (
[name] => Folder
[pos] => G
[pos_le] => R
)
[1] => Array (
[name] => Folder Two
[pos] => G
[pos_le] =>
)
)
)
*/

Related

How can I go deep by a variable amount into a multidimensional array in PHP?

I have a multidimensional array called $organized_comments and an array called $ancestors which is given by a function (unimportant) which lists all ancestors of an element in $organized_comments.
$organized_comments looks like this:
Array
(
[1] => Array
(
[id] => 1
[child] => Array
(
[id] => 2
[child] => Array
(
[id] => 3
[child] => Array
(
)
)
)
)
)
And I ran my function with the input as 3 and its output was $ancestors equal to [1,2] which means that 3 ancestors from farthest out to closest were 1 and then 2.
I want to make a function that runs through $ancestors in a way that when it reaches [id] => 3, I can insert a value into the [child] key.
What I tried was this:
$ancestors_count = count($ancestors);
$i = 0;
$thing = '$organized_comments';
foreach($ancestors as $parent_id_here) {
$i = $i + 1;
if ($i != $ancestors_count) {
$thing = $thing . "['$parent_id_here']";
} else {
///MY ACTION
}
}
But that obviously didn't work since I was just adding strings. What can I do to get to [id] => 3?
Thank you! Please tell me if I have been unclear at any point.
Based on your $thing concatenation logic, I conclude that ['child'] can only contain a single element, and array keys always match corresponding item id.
echo 'Before: ', json_encode($organized_comments, JSON_PRETTY_PRINT), "\n"; // more readable than print_r()
$ancestors = [1, 2];
$item = &$organized_comments;
foreach ( $ancestors as $ancestor_id ) {
$item = &$item[$ancestor_id]['child'];
}
if ( $item ) {
// $id = array_key_first($item); // php 7.3+
$id = array_keys($item)[0];
$item = &$item[$id];
// do your thing here
$item['foo'] = 'bar';
}
unset($item); // destroy reference to avoid accidental data corruption later
echo 'After: ', json_encode($organized_comments, JSON_PRETTY_PRINT), "\n";
Output:
Before: {
"1": {
"id": 1,
"child": {
"2": {
"id": 2,
"child": {
"3": {
"id": 3,
"child": []
}
}
}
}
}
}
After: {
"1": {
"id": 1,
"child": {
"2": {
"id": 2,
"child": {
"3": {
"id": 3,
"child": [],
"foo": "bar"
}
}
}
}
}
}

Return index of JSON subarray if some keys in it contain specific values

I have the following JSON response structure:
{
"response": {
"count": 14,
"posts": [
{
"id": 145,
"from_id": 5435435,
"to_id": 5435345,
"date": 1550434860,
"post_type": "post",
"text": "sometext",
},
{
"id": 144,
"from_id": 43242342432,
"to_id": 42342343243,
"date": 1550365480,
"post_type": "post",
"text": "sometext2",
},
{
"id": 143,
"from_id": 543543543,
"to_id": 534324645,
"date": 1550355299,
"post_type": "post",
"text": "sometext3",
},
//more items of the same structure here...
]
}
}
I can't even properly formulate it, but I need to write a function that conditionally returns posts[0] or posts[1] or posts[2], etc. if it contains specific value of the key text. I.e. if the condition is text == 'sometext', then the function must return posts[0] and so on.
I tried:
foreach ( $response->posts as $element ) {
if ( 'sometext' == $element->text ) {
var_dump($element);
return $element;
}
}
But it returns the whole contents of posts[0] and not the word posts[0]. I for the life of mine wasn't able to google up how to specify the index of the post instance in this chain: $response->posts->index_of_posts. Because the index is unknown and it's exactly what must be returned.
Please advice.
Assuming that this foreach loop is not in a function then you should not be using return but can use break to stop the loop. Note by using a foreach in the form foreach ($a as $key => $value) you can get the index of the post as well. Try something like this:
$response = $json->response;
foreach ( $response->posts as $key => $element ) {
if ( 'sometext' == $element->text ) {
break;
}
}
echo "found text in post $key\n";
print_r($element);
Output:
found text in post 0
stdClass Object (
[id] => 145
[from_id] => 5435435
[to_id] => 5435345
[date] => 1550434860
[post_type] => post
[text] => sometext
)
Demo on 3v4l.org
If you are in a function and want to return the index, then you could just do this and use the index value to access the appropriate post outside the function:
foreach ( $response->posts as $key => $element ) {
if ( 'sometext' == $element->text ) {
return $key;
}
}
Do this instead
$keep = [];
foreach ( $response->posts as $key=>$element ) {
if ( 'sometext' == $element->text ) {
$keep[] = "post[{$key}]"; //expected output ["post[0]"] or ["post[0]", "post[30]", ... ] for more then one.
//$keep[$key]= $element; //preserve keys
}
}
print_r($keep);
Not to hard.
PS I am surprised you put the string first, which is actually the better way to do it, but least intuitive. It's better because it avoids this:
if ( 'sometext' = $element->text ) //assignment
Type errors in code, as this will throw a error (because you cant assign a value to a string) whereas this:
if ( $element->text = 'sometext' ) //assignment
Would change the value of $element->text with no error.
Cheers!

How to Create Nested JSon With php

How do I create a JSON like this with PHP? I am trying to convert a dynamic data and save it into a MySQL database.
{
"fbd49440-a5a1-48be-b13e-e8efddad3588": {
"0": {
"value": "dsfrasdf5464356dfs hdhfg dfgh"
}
},
"0fc71cea-5609-40a7-a1d2-b78139660f8f": {
"0": {
"value": "50"
}
},
"73936e70-4329-4aba-b47c-42c64ced420c": {
"0": {
"file": "\/components\/com_djclassifieds\/images\/item\/25_juliet_ibrahim.jpg",
"uniqid": "59a352b96773325",
"title": "",
"file2": "",
"overlay_effect": "",
"caption": "",
"width": "",
"height": ""
},
"ac00b95e-9eeb-4035-bf4a-ff206319b2d6": {
"0": {
"value": "members-in-good-standing-2014",
"text": "",
"target": "0",
"custom_title": "",
"rel": ""
}
},
"69072346-fe4c-489e-8e2b-5a7d7409fd44": {
"0": {
"value": "34"
}
}
}
I tried the code below but it did not give me the result I want.
$json = (
"fbd49440-a5a1-48be-b13e-e8efddad3588"=> (
$array1
),
"0fc71cea-5609-40a7-a1d2-b78139660f8f"=> (
$array2
),
"73936e70-4329-4aba-b47c-42c64ced420c"=> (
$array3
),
"ac00b95e-9eeb-4035-bf4a-ff206319b2d6"=> (
$array4
),
"69072346-fe4c-489e-8e2b-5a7d7409fd44"=> (
$array5
)
)
echo json_encode($json);
I will be glad if someone could help me, thank you
json_encode will take multiple types of valid data and try to encode them into a json representation of it. It does require that the input is valid.
The code you have pasted has multiple syntax errors, and we cannot tell what is in your $array1. $array2, $array3, $array4, $array5. However a couple of changes (and assuming your $arrays are actual arrays) has your code working.
There are also bitmask options in the form of JSON Constants that will define how your JSON should be stored.
$array = array( "data" => "value"); // dummy array to show data working
$json = array( //defined the following as an array
"fbd49440-a5a1-48be-b13e-e8efddad3588"=> array( //notice each of these are now defined as arrays
$array
),
"0fc71cea-5609-40a7-a1d2-b78139660f8f"=> array(
$array
),
"73936e70-4329-4aba-b47c-42c64ced420c"=> array(
$array
),
"ac00b95e-9eeb-4035-bf4a-ff206319b2d6"=> array(
$array
),
"69072346-fe4c-489e-8e2b-5a7d7409fd44"=> array(
$array
)
); //added semicolon to end the declaration
echo json_encode($json, ( JSON_FORCE_OBJECT + JSON_PRETTY_PRINT ) );
// added JSON_FORCE_OBJECT and JSON_PRETTY_PRINT
// As bitmask options, they return a constant to give `json_encode` instructions
// JSON_FORCE_OBJECT => 16, JSON_PRETTY_PRINT => 128
// JSON_FORCE_OBJECT + JSON_PRETTY_PRINT = 16 + 128 = 144
// json_encode( $array, ( JSON_FORCE_OBJECT + JSON_PRETTY_PRINT ) = json_encode ($array, 144);
Returns
{"fbd49440-a5a1-48be-b13e-e8efddad3588":{"0":{"data":"value"}},"0fc71cea-5609-40a7-a1d2-b78139660f8f":{"0":{"data":"value"}},"73936e70-4329-4aba-b47c-42c64ced420c":{"0":{"data":"value"}},"ac00b95e-9eeb-4035-bf4a-ff206319b2d6":{"0":{"data":"value"}},"69072346-fe4c-489e-8e2b-5a7d7409fd44":{"0":{"data":"value"}}}
Array of Arrays in your json data.
If you want it to print the index of each result, that needs to be treated as an array as well. Simple enough to understand when there are multiple pairs in the result, less intuative when the result is one pair.
$array1 = array( "data" => "value");
echo json_encode($array1, JSON_FORCE_OBJECT );
//would return
//{"data":"value"}
$array2 = array(
array( "data" => "value" ),
array( "data" => "value" )
);
echo json_encode($array2, JSON_FORCE_OBJECT );
// would return
// {"0":{"data":"value"},"1":{"data":"value"}}
$array3 = array(
array( "data" => "value" )
);
echo json_encode($array3, JSON_FORCE_OBJECT );
// would return
// {"0":{"data":"value"}}

Prepend key value to array - PHP

I have the below code in a for..loop is there a way I can add values to the beginning of the array?
$data = array();
$initial = strtotime('11:00:00');
for (; $initial < strtotime("23:00:59"); $initial = strtotime("+15 minutes", $initial)) {
if ($initial > strtotime("+45 minutes", time())) {
$row['value'] = date('Hi', $initial);
$row['label'] = date('H:i', $initial);
$data['data'][] = $row;
}
}
I want to add the below values to the top of the array. I have tried using array_unshift but I don't think it supports key-value pairs.
if(!isBetween('22:00', '09:59', date('H:i'))) {
$row['value'] = "asap";
$row['label'] = "ASAP";
}
My array output
{
"data": [
{
"value": "1145",
"label": "11:45"
}
]
}
I want to get this
{
"data": [
{
"value": "asap",
"label": "ASAP"
},{
"value": "1145",
"label": "11:45"
},
]
}
Un-shift should work if you pass the arguments correctly:
array_unshift($data["data"], $prepend);
Alternatively, you could use array_merge, like this:
$data["data"] = array_merge(array($prepend), $data["data"]);
With the following example data:
$data = [
"data" => [
[
"value" => "1145",
"label" => "11:45"
]
]
];
$prepend = [
"value" => "asap",
"label" => "ASAP"
];
$data["data"] = array_merge(array($prepend), $data["data"]);
print_r($data);
You would get this output (with both solutions):
Array (
[data] => Array (
[0] => Array (
[value] => asap
[label] => ASAP
)
[1] => Array (
[value] => 1145
[label] => 11:45
)
)
)
If you need to prepend something to the array without the keys being reindexed and/or need to prepend a key value pair, you can use this short function:
function array_unshift_assoc(&$arr, $key, $val) {
$arr = array_reverse($arr, true);
$arr[$key] = $val;
return array_reverse($arr, true);
}
Source: http://php.net/manual/en/function.array-unshift.php

creating nested associative array from json code

I am creating an associative array from a json code so that i can use in my curl code that connects to an API. Now it seems like the associative array outputted is incorrect. I would like to format it correctly, but now I get message an error saying the array is incorrect.
The json code:
{
"payment": [
{
"clientCorrelator": "54321",
"endUserId": "tel:+16309700001",
"merchantCode": "01234",
"merchantPin": "1234",
"merchantNumber": "tel:+16309700001",
"notifyURL": "http://example.com/notifyURL",
"paymentAmount": {
"chargingInformation": [
{
"amount": "10",
"currency": "USD",
"description": "AlienInvadersGame"
}
],
"chargingMetaData": [
{
"onBehalfOf": "Example Games Inc",
"purchaseCategoryCode": "Game",
"channel": "WAP",
"taxAmount": "0"
}
],
"referenceCode": "REF-12345",
"transactionOperationStatus": "Charged"
}
}
]
}
The php code to build the array:
jasondata = file_get_contents("payment.json");
$json = json_decode($jasondata, true);
$payment = ($json['payment']) ;
print_r($payment);
The output:
Array ( [0] => Array ( [clientCorrelator] => 54321 [endUserId] => tel:+16309700001 [merchantCode] => 01234 [merchantPin] => 1234 [merchantNumber] => tel:+16309700001 [notifyURL] => http://example.com/notifyURL [paymentAmount] => Array ( [chargingInformation] => Array ( [0] => Array ( [amount] => 10 [currency] => USD [description] => AlienInvadersGame ) ) [chargingMetaData] => Array ( [0] => Array ( [onBehalfOf] => Example Games Inc [purchaseCategoryCode] => Game [channel] => WAP [taxAmount] => 0 ) ) [referenceCode] => REF-12345 [transactionOperationStatus] => Charged ) ) )
My main goal is to remove the [0] indexes without messing up the array. please assist
instead of $payment = ($json['payment']);
change that to $payment = reset($json['payment']);
However if there are multiple entries under payment, then you should just loop over them like:
foreach($json['payment'] as $payment){
print_r($payment);
}
The loop also would work if there was any number of elements under payment, so not just multiple.
more or less safe function
$payment = json_decode($str, true);
function RemoveZeroIndex(&$arr) {
foreach($arr as $key => &$item) { // walk array
if (is_array($item) && // if array
(count($item) === 1) && // with one item
isset($item[0])) // and numeric index
$item = $item[0]; // shift it
if (is_array($item))
RemoveZeroIndex($item); // call recursively
}
}
RemoveZeroIndex($payment);
print_r($payment);
In addition to Jonathan Khun.
For your nested arrays you just do the same. Reset the internal pointer of that array.
<?php
$jasondata = '{
"payment": [
{
"clientCorrelator": "54321",
"endUserId": "tel:+16309700001",
"merchantCode": "01234",
"merchantPin": "1234",
"merchantNumber": "tel:+16309700001",
"notifyURL": "http://example.com/notifyURL",
"paymentAmount": {
"chargingInformation": [
{
"amount": "10",
"currency": "USD",
"description": "AlienInvadersGame"
}
],
"chargingMetaData": [
{
"onBehalfOf": "Example Games Inc",
"purchaseCategoryCode": "Game",
"channel": "WAP",
"taxAmount": "0"
}
],
"referenceCode": "REF-12345",
"transactionOperationStatus": "Charged"
}
}
]
}';
$json = json_decode($jasondata, true);
$payment = reset($json['payment']);
$payment['paymentAmount']['chargingInformation'] = reset($payment['paymentAmount']['chargingInformation']);
$payment['paymentAmount']['chargingMetaData'] = reset($payment['paymentAmount']['chargingMetaData']);
echo "<pre>";
print_r($payment);
?>

Categories