PHP Object array access with variable - php

I have a sample object array as a variable $xmlobj
SimpleXMLElement Object(
[SearchId] => 10769920113727_1556288871357_170040
[Categories] => SimpleXMLElement Object
(
[#attributes] => Array
(
[total_subcategories] => 1
)
[SubCategory] => SimpleXMLElement Object
(
[Title] => Reproductor MP3 y Multimedia
[Value] => 122701
[NumberOfProducts] => 1
)
)
[Products] => SimpleXMLElement Object
(
[#attributes] => Array
(
[totalResultsAvailable] => 1
[firstResultPosition] => 1
[totalResultsReturned] => 1
[currency] => EUR
[totalMerchantsAvailable] => 1
[searchOperator] => and
)
[Product] => SimpleXMLElement Object
(
[Offer] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => f94af9ec5186b53051c9ccf083ebddec
[type] => MANUFACTURER_PRODUCTS
)
[Title] => Apple iPod Nano 6 8 GB Gris
[Description] => iPod Nano 6 8 GB - Gris
[LastModified] => 2019-04-26 01:10:56
[MobileFriendly] => false
[Merchant] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 15348713
)
[Name] => Backmarket
)
[Price] => SimpleXMLElement Object
(
[#attributes] => Array
(
[currency] => EUR
)
[Price] => 99.99
[DeliveryCost] => 19.9
[DeliveryCostDetails] => SimpleXMLElement Object
(
[DeliveryCost] => 19.9
)
[TotalPrice] => 119.89
[PriceWithoutRebate] => 190
[Rebate] => 47
)
[ProductClass] => 2
[Availability] => 1
[DeliveryTime] => 24H / 4 días laborables
[Promo] => SimpleXMLElement Object
(
)
[OffensiveContent] => false
[FinancingOption] => SimpleXMLElement Object
(
)
[MerchantCategory] => Alta Tecnología Imágenes y sonidos Reproductor de MP3 Y MP4
[Brand] => Apple
[BrandId] => 211
[GreenProduct] => false
)
)
)
Now when I want to access e.g. price i do it like this:
$product_total_price = $xmlobj->Products->Product->Offer->Price->TotalPrice;
And it's OK - I get what I want, but I am having issue when I want "dynamically" to change what I am looking for like:
$search_part = "Products->Product->Offer->Price->TotalPrice";
$product_total_price = $xmlobj->$search_part;
I obviously get nothing... even when I try:
$product_total_price = $xmlobj."->".$search_part;
So my question is... how to do it ? :)
Thanks !

You will have to construct the path by exploding into an array, then looping to get each property.
For example...
$searchPart = "Products->Product->Offer->Price->TotalPrice";
$searchPath = explode('->', $searchPart);
$current = $xmlobj;
foreach ($searchPath as $segment) {
$current = $current->$segment;
}
var_dump($current);
or you can convert it to an array and then you will be able to get your attributes
$xml = simplexml_load_string($xmlobj);
$json = json_encode($xml);
$arr = json_decode($json,TRUE);
$parseString = 'Products->Product->Offer->Price->#attributes->currency';
$parsePath = explode('->', $parseString);
$current = $arr;
foreach ($parsePath as $segment) {
$current = $current[$segment];
}
var_dump($current);

You can take a look at eval that take your code as a string and evaluates it, but I strongly discourage its usage because it's a potentially (and very big) security hole.
Instead you could use explode passing as first argument -> and then loop over the resulting array to get the value you need:
$search_part = "Products->Product->Offer->Price->TotalPrice";
$chunks = explode("->", $search_part);
foreach ($chunks as $chunk) {
$temp = $xmlobj[$chunk];
}
$product_total_price = $temp;
or something similar, and then you will get you price dynamically
Note that if $xmlObj is of type Object you will need to use $xmlObj->{$chunk} instead of $xmlobj[$chunk]

Related

Retrieve a value from JSON Object using PHP (Shiprocket API)

I am getting below json data thru Shiprocket API. Now I want to extract value of below variables in PHP code from this json.
I have tried to use json_decode but it did not work and show null value:
$data = json_decode($json);
$sr_status = $data['shipment_status'];
Please suggest the code to retrieve below variables value.
shipment_status , awb_code , courier_company_id
Array
(
[0] => stdClass Object
(
[tracking_data] => stdClass Object
(
[track_status] => 1
[shipment_status] => 7
[shipment_track] => Array
(
[0] => stdClass Object
(
[id] => 180339484
[awb_code] => 11150911492
[courier_company_id] => 55
[shipment_id] => 1711169662
[order_id] => 233223781187
[pickup_date] => 2023-01-11 03:02:00
[delivered_date] => 2023-01-16 12:22:00
[weight] => 0.25
[packages] => 1
[current_status] => Delivered
[delivered_to] => Solapur
[destination] => Solapur
[consignee_name] => ABC
[origin] => Ludhiana
[courier_agent_details] =>
[edd] =>
)
)
[shipment_track_activities] => Array
(
[0] => stdClass Object
(
[date] => 2023-01-16 12:22:00
[status] => 000-T-DL
[activity] => SHIPMENT DELIVERED
[location] => SOLAPUR
[sr-status] => 7
[sr-status-label] => DELIVERED
)
[1] => stdClass Object
(
[date] => 2023-01-16 11:34:00
[status] => 002-S-UD
[activity] => SHIPMENT OUTSCAN
[location] => SOLAPUR
[sr-status] => 17
[sr-status-label] => OUT FOR DELIVERY
)
)
[track_url] => https://shiprocket.co//tracking/11150911492
[etd] => 2023-01-14 17:02:00
[qc_response] => stdClass Object
(
[qc_image] =>
[qc_failed_reason] =>
)
)
)
)
you can try this:
$array = ...; // Your array here
$data= json_decode($array);
$shipment_status = $data[0]->tracking_data->shipment_status;
$awb_code = $data[0]->tracking_data->shipment_track[0]->awb_code;
$courier_company_id = $data[0]->tracking_data->shipment_track[0]->courier_company_id;
Or use $data = json_decode($json,true); which return an array where you can use
foreach($data as $val) {
$shipment_status = $val['tracking_data']['shipment_status'];
foreach ($val['shipment_track'] as $value) {
$awb_code = $value['awb_code'];
$courier_company_id = $value['courier_company_id'];
}
}

Parse XML to Array with SimpleXML

I've that xml structure retrieving from device
<packet>
<info action="fiscalmemory" fiscalmemorysize="1048576" recordsize="464" fiscal="1" uniqueno="ABC12345678" nip="123-456-78-90" maxrecordscount="2144" recordscount="7" maxreportscount="1830" reportscount="4" resetmaxcount="200" resetcount="0" taxratesprglimit="30" taxratesprg="1" currencychangeprglimit="4" currencychangeprg="0" fiscalstartdate="dd-mm-yyyy hh:dd:ss" fiscalstopdate="dd-mm-yyyy hh:dd:ss" currencyname="PLN" />
<ptu name="A" bres="Nobi">123.23</ptu>
<ptu name="B">123.23</ptu>
<ptu name="D">8</ptu>
<sale>999.23</sale>
</packet>
simpleXml does't see ptu's attributes
$array = simplexml_load_string($xml);
print_r($array);
It prints
SimpleXMLElement Object
(
[info] => SimpleXMLElement Object
(
[#attributes] => Array
(
[action] => fiscalmemory
[fiscalmemorysize] => 1048576
[recordsize] => 464
[fiscal] => 1
[uniqueno] => ABC12345678
[nip] => 123-456-78-90
[maxrecordscount] => 2144
[recordscount] => 7
[maxreportscount] => 1830
[reportscount] => 4
[resetmaxcount] => 200
[resetcount] => 0
[taxratesprglimit] => 30
[taxratesprg] => 1
[currencychangeprglimit] => 4
[currencychangeprg] => 0
[fiscalstartdate] => dd-mm-yyyy hh:dd:ss
[fiscalstopdate] => dd-mm-yyyy hh:dd:ss
[currencyname] => PLN
)
)
[ptu] => Array
(
[0] => 123.23
[1] => 123.23
[2] => 8
)
[sale] => 999.23
)
As we can see ptu doesn't contain attributes :/
I also tried parse it with recursive function because children also may contain chilren but without success :/
Could anybody point to me why SimpleXML doesn't take ptu's attributes and also share any parsing function?
Thanks in advance.
edited
As regards Nigel Ren I made that function
function parseXMLtoArray($xml){
$x = simplexml_load_string($xml);
$result = [];
function parse($xml, &$res){
$res['name'] = $xml->getName();
$res['value'] = $xml->__toString();
foreach ($xml->attributes() as $k => $v){
$res['attr'][$k] = $v->__toString();
}
foreach($xml->children() as $child){
parse($child, $res['children'][]);
}
}
parse($x, $result);
return $result;
}
$resArray = parseXMLtoArray($rawXml);
print_r($resArray);
this returns such array
Array
(
[name] => packet
[value] =>
[attr] => Array
(
[crc] => BKJFKHKD54
)
[children] => Array
(
[0] => Array
(
[name] => info
[value] =>
[attr] => Array
(
[action] => fiscalmemory
[fiscalmemorysize] => 1048576
[recordsize] => 464
[fiscal] => 1
[uniqueno] => ABC12345678
[nip] => 123-456-78-90
[maxrecordscount] => 2144
[recordscount] => 7
[maxreportscount] => 1830
[reportscount] => 4
[resetmaxcount] => 200
[resetcount] => 0
[taxratesprglimit] => 30
[taxratesprg] => 1
[currencychangeprglimit] => 4
[currencychangeprg] => 0
[fiscalstartdate] => dd-mm-yyyy hh:dd:ss
[fiscalstopdate] => dd-mm-yyyy hh:dd:ss
[currencyname] => PLN
)
)
[1] => Array
(
[name] => ptu
[value] => 123.23
[attr] => Array
(
[name] => A
)
)
[2] => Array
(
[name] => ptu
[value] => 123.23
[attr] => Array
(
[name] => B
)
)
[3] => Array
(
[name] => ptu
[value] => 8
[attr] => Array
(
[name] => D
)
)
[4] => Array
(
[name] => sale
[value] => 999.23
)
)
)
Is this correct?
Thanks again Nigel
When loading with SimpleXML, using print_r() gives only an idea of the content and doesn't have the full content. If you want to see the full content then use ->asXML()...
$array = simplexml_load_string($xml);
echo $array->asXML();
To check the attributes of <ptu> element, (this just gives the first one)...
echo $array->ptu[0]['name'];
This uses ->ptu to get the <ptu> element and takes the first one [0] and then takes the name attribute using ['name'].

Convert php array into xml file

How can I convert this PHP array into XML? I am using PHP codegniter. Is there any method or library for converting an array into XML? Here is my PHP array code. What am I doing wrong?
Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 1
)
[timecode] => 12:23:55:142
[datetimecode] => 11:30:01:06 2016/10/14
[color] => Green
[user] => logger 1
[comment] => Jdjd
[framecode] => 1115899
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 2
)
[timecode] => 06:12:04:02
[datetimecode] => 11:30:05:15 2016/10/14
[color] => Magenta
[user] => logger 1
[comment] => Ndnnd
Ndnnd
[framecode] => 558109
)
[2] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 3
)
[timecode] => 06:12:13:17
[datetimecode] => 12:32:34:07 2016/10/14
[color] => White
[user] => logger 1
[comment] => Dd
[framecode] => 558349
)
)
I found this by googling
How to convert array to SimpleXML
You have an array of simple SimpleXMLElement Objects
so
$xml = new SimpleXMLElement('<root/>');
foreach ($my_array as $key => $value) {
$node = "node" . $key;
$xml->addChild($node, $value);
}
That should add <node0>, <node1>, <node2>
That is if $value behaves well. I did not test.

Filtering an Array

I'm working on a website that displays properties. I have a huge XML feed in which I put into an array.
function search_results($department = '', $post_code = '', $min_price = '', $max_price = '', $type = '', $bedrooms = '') {
foreach($this->xml->property as $property) {
if($property->department == $department) {
$this->properties[] = $property;
}
}
$this->filter_results();
}
this first filters the XML based on the department such as 'For Sale' or 'To Rent'. I want to now be able to search this array based on the variables I pass though the function. For example:
if($this->properties->regionID == $post_code) {
$this->properties[] = $property;
}
But this doesn't work. This will be in a class called Results. How will I go about searching the array. I had a look at using array_filter(); but I couldn't get it working it would return Array() when I print_r it.
Does anyone know how to search/filter an array?
This is what the array looks like when I print_r:
Array ( [0] => SimpleXMLElement Object ( [propertyID] => 1 [branchID] => 1 [clientName] => Name [branchName] => Branch [department] => Lettings [referenceNumber] => 1 [addressName] => 4 [addressNumber] => SimpleXMLElement Object ( ) [addressStreet] => address [address2] => address2 [address3] => address3 [address4] => SimpleXMLElement Object ( ) [addressPostcode] => postcode [country] => postcode [displayAddress] => address [propertyBedrooms] => 1 [propertyBathrooms] => 1 [propertyEnsuites] => 0 [propertyReceptionRooms] => 1 [propertyKitchens] => 1 [displayPropertyType] => Flat/Apartment [propertyType] => 2 [propertyStyle] => 16 [propertyAge] => 0 [floorArea] => 0.00 [floorAreaUnits] => sq ft [propertyFeature1] => Converted School House [propertyFeature2] => City Centre Location [propertyFeature3] => Modern Fittings [propertyFeature4] => SimpleXMLElement Object ( ) [propertyFeature5] => SimpleXMLElement Object ( ) [propertyFeature6] => SimpleXMLElement Object ( ) [propertyFeature7] => SimpleXMLElement Object ( ) [propertyFeature8] => SimpleXMLElement Object ( ) [propertyFeature9] => SimpleXMLElement Object ( ) [propertyFeature10] => SimpleXMLElement Object ( ) [rent] => 525 [rentFrequency] => 1 [toLetPOA] => 0 [studentProperty] => SimpleXMLElement Object ( ) [availability] => 2 [mainSummary] => summary. [fullDescription] => SimpleXMLElement Object ( ) [dateLastModified] => 2014-05-02 [featuredProperty] => 0 [regionID] => 27 [latitude] => SimpleXMLElement Object ( ) [longitude] => SimpleXMLElement Object ( ) [flags] => SimpleXMLElement Object ( ) [images] => SimpleXMLElement Object ( [image] => Array ( [0] => image [1] => image [2] => image [3] => image [4] => image ) ))
Does anyone know how I would be able to search this query for example
$post_code = 43; $min_price = 300; $max_price = 500
and so on.
Looking at the code, the logic seems good to me.
There is something though that might cause the issue.
On line 4 of your code, you have:
$this->properties[] = $property;
It means that you have an array of properties.
But then, you are trying to access the object directly:
if($this->properties->regionID == $post_code) {
$this->properties[] = $property;
}
This looks strange to me. You are trying to see if an abject has the property you want, and then save the same object as it is an array.
So I guess, once you have built your $this->properties array, you just have to loop through it and apply your filters to return an array of properties with just what you are looking for:
foreach($this->properties as $singleProperty)
{
if($singleProperty->regionID == $post_code)
{
$this->foundProperties[] = $singleProperty;
}
}

Use a foreach loop to access the array within this queryresult object?

A print_r of my object ($results) returns the following:
QueryResult Object
( [queryLocator] => [done] => 1 [records] =>
Array ( [0] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0167 [Partner_Research_Name__c] => MM Sample Organization-TBR Partner 2011 [Id] => a0V80000003FwjjEAC ) [Id] => a0V80000003FwjjEAC )
[1] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0170 [Partner_Research_Name__c] => Kansas City, Missouri Public Schools-TBR Partner 2011 [Id] => a0V80000003Fxf9EAC ) [Id] => a0V80000003Fxf9EAC )
[2] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0169 [Partner_Research_Name__c] => Newark Public Schools-TBR Partner 2011 [Id] => a0V80000003FxQ2EAK ) [Id] => a0V80000003FxQ2EAK )
[3] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0168 [Partner_Research_Name__c] => Breakthrough Charter Schools-TBR Partner 2011 [Id] => a0V80000003FxPxEAK ) [Id] => a0V80000003FxPxEAK )
[4] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0004 [Partner_Research_Name__c] => KIPP, San Antonio-TBR Partner 2011 [Id] => a0V80000003FrBUEA0 ) [Id] => a0V80000003FrBUEA0 )
[5] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0003 [Partner_Research_Name__c] => KIPP, Chicago - Gary-TBR Partner 2011 [Id] => a0V80000003FrB5EAK ) [Id] => a0V80000003FrB5EAK )
[6] => SObject Object ( [type] => Partner_Research__c [fields] => stdClass Object ( [Partner_Research_URL__c] => http://www.forms.com/184320?tfa_PRID=PR-0023 [Partner_Research_Name__c] => Harlem Village Academies-TBR Partner 2011 [Id] => a0V80000003FrEOEA0 ) [Id] => a0V80000003FrEOEA0 ) ) [size] => 7 )
I want to use a loop similar to the what is shown below to display a series of results however the foreach statement is incorrect.
foreach ($results as $result)
{
$id = $result[fields][Id];
$name = $result[fields][Partner_Research_Name__c];
$url = $result[fields][Partner_Research_URL__c];
$html .= "<tr><td>$id</td><td>$name</td><td>$url</td></tr>";
}
What changes do I need to make to the foreach statement to get my code back on track?
What helps me in problems like this is to try to print inside the foreach loop. For example, you can do a var_dump of each $result and see what that structure is, and it could help determine how to proceed.
Here is how I eventually did it, thanks for the help provided by contributors.
foreach ($results->records as $result)
{
$id = $result->fields->Id;
$name = $result->fields->Partner_Research_Name__c;
$url = $result->fields->Partner_Research_URL__c;
$html .= "<tr><td>$id</td><td>$name</td><td>$url</td></tr>";
}
$results is the name of the QueryResults object, I don't know what the real name in your code is.
foreach ($results->records as $result)
{
$id = $result->Id;
$name = $result->fields->Partner_Research_Name__c;
$url = $result->fields->Partner_Research_URL__c;
$html .= "<tr><td>$id</td><td>$name</td><td>$url</td></tr>";
}
If I'm reading your sample correctly, your items are std objects instead of arrays. You may need to reference them like this:
foreach ($results as $result)
{
$id = $result->fields->Id;
$name = $result->fields->Partner_Research_Name__c;
$url = $result->fields->Partner_Research_URL__c;
$html .= "<tr><td>$id</td><td>$name</td><td>$url</td></tr>";
}
Your print_r sample above is difficult to read. If you could provide it with the indentation it would be helpful.

Categories