Removing elements from an associative array - php

This post describes how to remove an element of an associative array with Unset i.e unset($array['key1']);
I have this array:
Array
(
[queryLocator] =>
[done] => 1
[records] => Array
(
[0] => stdClass Object
(
[Id] =>
[CreatedDate] => 2016-08-28T14:43:45.000Z
[Leader__c] => GF
[Location__c] => Postbridge
[Service_Date__c] => 2016-09-03
[Service_Time__c] => 14:30
[Service_Type__c] => Baptism
)
)
[size] => 42
[pointer] => 0
[QueryResultsf] => SforceEnterpriseClient Object
(
[sforce:protected] => SoapClient Object
(
[trace] => 1
[compression] => 32
[_encoding] => utf-8
[_features] => 1
[_user_agent] => salesforce-toolkit-php/20.0
[_soap_version] => 1
[sdl] => Resource id #8
[packageVersionHeader:protected] =>
[client_id:protected] =>
)
)
)
I want to delete the key [queryLocator], replace the key [done] with [total], replace the key [records] with [rows] and delete all subsequent keys i.e [size], [pointer] etc.
Using unset, i.e unset($array['queryLocator']); has no effect.
What am I doing wrong ? Thanks.

Here is the code that achieves what I wanted - taking output from a Sales Force query and formatting it as required by a EasyUI datagrid.
//--Get the Sales Force Data
$response = $mySforceConnection->query($query);
//--Encode and decode - for some reason
$data = json_encode((array)$response);
$x = json_decode($data,true);
//--Empty Array
$q = array();
//--Add array element for number records
$q['total'] = $numRecs;
//--Copy the array element from original query with data
$q['rows'] = $x['records'];
//--JSON Encode the new array
$y = json_encode($q);
//--Return the array to Ajax call
echo ($y);
And here's a snippet of the validated JSON..
{
"total":193,
"rows":[
{
"Id":null,
"CreatedDate":"2016-08-28T14:43:45.000Z",
"Leader__c":"GF",
"Location__c":"Postbridge",
"Service_Date__c":"2016-09-03",
"Service_Time__c":"14:30",
"Service_Type__c":"Baptism"
},
{
"Id":null,
"CreatedDate":"2016-08-17T20:43:10.000Z",
"Leader__c":"GF",
"Location__c":"Ashburton",
"Service_Date__c":"2016-09-04",
"Service_Time__c":"08:00",
"Service_Type__c":"HC 2"
},
{
"Id":null,
"CreatedDate":"2016-08-17T20:43:10.000Z",
"Leader__c":"GF",
"Location__c":"Bickington",
"Service_Date__c":"2016-09-04",
"Service_Time__c":"09:00",
"Service_Type__c":"HC 2"
},
{
"Id":null,
"CreatedDate":"2016-08-17T20:43:10.000Z",
"Leader__c":"MC",
"Location__c":"Holne",
"Service_Date__c":"2016-09-04",
"Service_Time__c":"10:30",
"Service_Type__c":"HC 1"
},
I struggled a bit with the array manipulation but it works. Any code improvement suggestions most welcome !

Related

Decoding JSON in PHP can't access the first key

I have a PHP script which successfully decodes a JSON string into a PHP object using:
$amount_detail = json_decode($tuitionfee->amount_detail);
when I print it out, this is what I get
stdClass Object
(
[1] => stdClass Object
(
[amount] => 0
[date] => 2023-01-08
[amount_discount] => 55200
[amount_fine] => 0
[description] =>
[collected_by] => Super Admin(356)
[payment_mode] => Cash
[received_by] => 1
[inv_no] => 1
)
[2] => stdClass Object
(
[amount] => 36800
[date] => 2023-01-08
[description] => Collected By: Super Admin
[amount_discount] => 0
[amount_fine] => 0
[payment_mode] => Cash
[received_by] => 1
[inv_no] => 2
)
)
In trying to get the first object [amount_discount], I went further to do this:
if (is_object($amount_detail)) {
foreach ($amount_detail as $amount_detail_key => $amount_detail_value) {
$discount = $amount_detail_value->amount_discount;
}
}
But this is collecting data from the second key [amount_discount].
So instead of getting 55200, I'm getting 0.
How do I get to access data from the first key too?
The $discount variable gets over-written each time loop is executed. So you will always get the last data.
So if you want only the first index value then use current()
$discount = current((Array)$amount_detail_value)->amount_discount;
Output: https://3v4l.org/8Wvqv
Note: In case you want all discount output then in your loop echo the $discount variable.

PHP search JSON without looping

I have a large JSON array which is the result of querying the API of an Icinga2 monitoring system.
I have used json_decode like this in my code to decode it:
$response = json_decode($array, true);
and I can see the output looks like this:
Array
(
[results] => Array
(
[0] => Array
(
[attrs] => Array
(
[__name] => HOSTNAME0
[acknowledgement] => 0
[acknowledgement_expiry] => 0
...
...
[state] => 0
[state_type] => 1
[meta] => Array
(
)
[name] => HOSTNAME0
[type] => Host
)
[1] => Array
(
[attrs] => Array
(
[__name] => HOSTNAME1
[acknowledgement] => 0
[acknowledgement_expiry] => 0
...
...
[state] => 0
[state_type] => 1
[meta] => Array
(
)
[name] => HOSTNAME1
[type] => Host
)
There are 400 Records in total and it's quite a complex structure but the only bits I am really interested in are the name and state fields.
Basically my script has a list of 150 hostnames from another source and what I want to do is for each hostname, search for it in the array and return the value of the state field for that host.
So far I've been struggling to do this without looping through the entire array for each of the 150 hostnames. There must be a more efficient way to do a lookup in the array based on a hostname and return a single value but I can't figure it out.
Given, the name field has no logical sorting inside the json result, there is no way to look at least once at each element. If they are sorted alphabetical, you could use a simple binary search, which would give you the result in O(log(n)).
The other thing is, if you have to search for multiple names, you could put them inside an name assiciated array. This way, you only have an initial overhead of O(n) building the list and each following search would return you the state on O(1).
// building the array
$states = [];
foreach ($items as $item) {
$states[$item['name']] = $item['state'];
}
looking for HOSTNAME1
$state = $states['HOSTNAME1'];
I'm hoping that I've got the source data array in the correct layout as the format was a bit confusing from the original question. But the main idea is to use array_column to extract the "attrs" and key the result by the "name" element of this array.
$response = Array(
"results" => Array(
0 => Array(
"attrs" => Array(
"__name" => "HOSTNAME0",
"acknowledgement" => 0,
"acknowledgement_expiry" => 0,
"state" => 0,
"state_type" => 1
),
"name" => "HOSTNAME0",
"type" => "Host"
),
1 => Array(
"attrs" => Array(
"__name" => "HOSTNAME1",
"acknowledgement" => 0,
"acknowledgement_expiry" => 0,
"state" => 2,
"state_type" => 1
),
"name" => "HOSTNAME1",
"type" => "Host1"
)
)
);
$extract = array_column($response["results"], "attrs", "name");
print_r($extract);
With the sample data, this gives...
Array
(
[HOSTNAME0] => Array
(
[__name] => HOSTNAME0
[acknowledgement] => 0
[acknowledgement_expiry] => 0
[state] => 0
[state_type] => 1
)
[HOSTNAME1] => Array
(
[__name] => HOSTNAME1
[acknowledgement] => 0
[acknowledgement_expiry] => 0
[state] => 2
[state_type] => 1
)
)
So to find any server by name, you'd use
echo "HOSTNAME1=".$extract["HOSTNAME1"]["state"].PHP_EOL;
If you only wanted the state field (as you asked for) and wanted to simplify the array, you can then use...
array_walk($extract, function(&$data) {$data=$data["state"];});
print_r($extract);
The array_walk() goes through the array and just copies the state field to be the entry, so the result of this is...
Array
(
[HOSTNAME0] => 0
[HOSTNAME1] => 2
)
So now you just do...
echo "HOSTNAME1=".$extract["HOSTNAME1"].PHP_EOL;

Cycling an array and delete item

I need help :)
I've to code a script that, cycling through an array inside an array , delete an element if in XXX field there isn't value (is NULL ).
My array is:
Array (
[idCampaign] => 3
[idIT] => 322
[recipients] =>Array (
[0] => stdClass Object ( [name] => minnie [email] => blabla#gmail.com [XXX] => )
[1] => stdClass Object ( [name] => [email] => fddd#gmail.it [XXX] => 0.88451100 )
) ) [date] => MongoDate Object ( [sec] => 1468503103 [usec] => 0 ) )
In this example the item [0] has no value in XXX value so my output array will be:
Array (
[idCampaign] => 3
[idIT] => 322
[recipients] =>Array (
[1] => stdClass Object ( [name] => [email] => fddd#gmail.it [XXX] => 0.88451100 )
) ) [date] => MongoDate Object ( [sec] => 1468503103 [usec] => 0 ) )
i hope that you can help me :)
You could use a nested foreach() Loop to cycle through the Data and then perform some tests, which on failing, guarantees that it is safe to unset the pertinent variable. Here's how:
<?php
// WE SIMULATE SOME DATA TO POPULATE THE ARRAY, ONLY FOR TESTING PURPOSES
$objDate = new stdClass();
$objRez1 = new stdClass();
$objRez2 = new stdClass();
$objRez1->name = "minnie";
$objRez1->email = "blabla#gmail.com";
$objRez1->XXX = null;
$objRez2->name = null;
$objRez2->email = "fddd#gmail.it";
$objRez2->XXX = 0.88451100;
$objDate->sec = 1468503103;
$objDate->usec = 0;
// IN THE END WE NOW HAVE A SAMPLE ARRAY (SIMULATED) TO WORK WITH.
$arrData = array(
'idCampaign' => 3,
'idIT' => 322,
'recipients' => array(
$objRez1,
$objRez2
),
'date' =>$objDate,
);
// LOOP THROUGH THE ARRAY OF DATA THAT YOU HAVE
// NOTICE THE &$data IN THE LOOP CONSTRUCT...
// THIS IS NECESSARY FOR REFERENCING WHEN WE UNSET VARIABLES WITHIN THE LOOP
foreach($arrData as $key=>&$data){
// SINCE THE XXX KEY IS STORED IN THE 'recipients' ARRAY,
// WE CHECK IF THE CURRENT KEY IS 'recipients' & THAT $data IS AN ARRAY
if($key == "recipients" && is_array($data)){
// NOW WE LOOP THROUGH THE DATA WHEREIN THE 'XXX' KEY LIVES
foreach($data as $obj){
// IF THE VALUE OF THE XXX KEY IS NULL OR NOT SET,
// WE SIMPLY UNSET IT...
if(!$obj->XXX){
unset($obj->XXX);
}
}
}
}
var_dump($arrData);
You can verify the Results HERE.
Hope this could offer you a little tip on how to implement it rightly on your own...
This should do the job
foreach($arrayOfObjects as $index => $object){
if(!isset($object->xxx) || empty($object->xxx)){
unset($arrayOfObjects[$index]);
}
}

JSON PHP Decode

i have an extern JSON File and no problems to get Airline, Price, etc..
But how can i get [ACE] ?
[success] => 1
[data] => Array
(
[ACE] => Array
(
[0] => Array
(
[price] => 477
[airline] => AB
[flight_number] => 2434
[departure_at] => 2014-08-09T12:30:00Z
[return_at] => 2014-08-24T08:35:00Z
[expires_at] => 2014-04-03T22:46:17Z
)
)
$foo = $json['data']['ACE']; should do it.
Unless you want to get the key from the $data array, in which case:
foreach ($json['data'] as $k=>$v) {
$foo = $k; // this is 'ACE'.
break;
}
Edited as per comment.
['ACE'] is an array?
Your getting the data from it starting with the first - [0]
Then the ['price'] of the first one?

Problem With SimpleXML Parsing WoWArmory attributes

This is an example item:
SimpleXMLElement Object
(
[#attributes] => Array
(
[displayInfoId] => 62116
[durability] => 100
[gem0Id] => 41401
[gem1Id] => 40123
[gem2Id] => 0
[gemIcon0] => inv_jewelcrafting_shadowspirit_02
[gemIcon1] => inv_jewelcrafting_gem_37
[icon] => inv_helmet_98
[id] => 48592
[level] => 245
[maxDurability] => 100
[name] => Liadrin's Headpiece of Triumph
[permanentEnchantIcon] => ability_warrior_shieldmastery
[permanentEnchantItemId] => 44876
[permanentenchant] => 3819
[pickUp] => PickUpLargeChain
[putDown] => PutDownLArgeChain
[randomPropertiesId] => 0
[rarity] => 4
[seed] => 0
[slot] => 0
)
)
I'm trying to get a JSON object with each item, but there's about 17 or something, and if I try to json_encode() it's giving me "#attributes" as an object containing all the stuff I want. Help?
Something like this:
<?php
$sxm = new SimpleXMLElement("<a name=\"kkk\" other=\"foo\"/>");
$attrs = $sxm->attributes();
var_dump(json_encode(reset($attrs)));
gives:
string(28) "{"name":"kkk","other":"foo"}"
The problem you were experiencing was because $xmlObj->attributes() returns a SimpleXMLElement that, when converted as an array, is an array with the key "#attributes" and a value with an array that actually has the attributes as (name => value) pairs.
How about this
$jsonArray = array();
foreach ($xmlObj->attributes() as $attr => $value) {
$jsonArray[$attr] = (string)$value;
}
$jsonString = json_encode($jsonArray);
Edit: You may also be able to simply use
$jsonString = json_encode($xmlObj->attributes());
however I'm not sure if the attribute values are returned as strings or objects (edit - turns out you can't. See Artefacto's solution).
How about this?
$array = (array)$simplexml->node->attributes();
$jsonArray = json_encode($array['#attributes']);

Categories