Check if it is an array from SimpleXMLElement object - php

I have a problem with the follow php object dump. I try to check if "price" is an array, php return me always false. var_dump() of array "price" return me first element of array and not the entire array. Which is wrong? How can I check if it is an array?
object(SimpleXMLElement)#197 (1) {
["price"]=> array(4) {
[0]=> object(SimpleXMLElement)#156 (4) {
["room_id"]=> string(4) "1755"
["room_seq"]=> string(1) "1"
["offer_id"]=> string(4) "5842"
["price_total"]=> object(SimpleXMLElement)#205 (2) {
["price_typ"]=> string(1) "0"
["price_hb"]=> string(4) "2450"
}
}
[1]=> object(SimpleXMLElement)#143 (4) {
["room_id"]=> string(5) "24206"
["room_seq"]=> string(1) "1"
["offer_id"]=> string(4) "5842"
["price_total"]=> object(SimpleXMLElement)#205 (2) {
["price_typ"]=> string(1) "0"
["price_hb"]=> string(4) "2450"
}
}
[2]=> object(SimpleXMLElement)#135 (4) {
["room_id"]=> string(4) "1755"
["room_seq"]=> string(1) "1"
["offer_id"]=> string(6) "415725"
["price_total"]=> object(SimpleXMLElement)#205 (2) {
["price_typ"]=> string(1) "0"
["price_hb"]=> string(6) "2327.5"
}
}
[3]=> object(SimpleXMLElement)#136 (4) {
["room_id"]=> string(5) "24206"
["room_seq"]=> string(1) "1"
["offer_id"]=> string(6) "415725"
["price_total"]=> object(SimpleXMLElement)#205 (2) {
["price_typ"]=> string(1) "0"
["price_hb"]=> string(6) "2327.5"
}
}
}
}

Consider a simplified example:
<root>
<element>first</element>
<element>second</element>
<element>third</element>
</root>
$root->element is not really an array. It is SimpleXMLElement object. You can think of it as a selector, a collection of elements you can traverse using foreach and also access specific object using indexes:
$root->element[0]; //first object
$root->element[1]; //second
$root->element[2]; //third
Here is more examples of basic usage: http://php.net/manual/en/simplexml.examples-basic.php
So the real question is: How to define if there is more than one element in collection ?
You can do it using count() method:
if($es->result->hotel->channel->room_price->price->count() > 1){
echo 'many elements';
}
Read more: http://php.net/manual/en/simplexmlelement.count.php

// simplexml_load_string() return false if not $XML
$xml = simplexml_load_string($pSdata);
if(gettype($xml)=='object')
{
print_r(simplexmlArray($xml));
} else {
echo "no xml input";
}
// simplexml_load $xml obj to array
function simplexmlArray ( $xmlObject, $out = array () )
{
foreach ( (array) $xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) ) ? simplexmlArray ( $node ) : $node;
return $out;
}

Related

search multi-dimentional array for matching elements

I have a multi dimensional array. I need to search through the arrays and retrieve instance of dates that match each other.
This is my array:
$dateArray = array(8) {
[0]=>
array(15) {
["bookable_id"]=>
string(1) "1"
["event_date"]=>
string(10) "2019-09-11"
}
[1]=>
array(15) {
["bookable_id"]=>
string(1) "1"
["event_date"]=>
string(10) "2019-09-11"
}
[2]=>
array(15) {
["bookable_id"]=>
string(1) "4"
["event_date"]=>
string(10) "2019-10-17"
}
[3]=>
array(15) {
["bookable_id"]=>
string(1) "4"
["event_date"]=>
string(10) "2019-10-17"
}
[4]=>
array(15) {
["bookable_id"]=>
string(1) "3"
["event_date"]=>
string(10) "2020-09-15"
}
[5]=>
array(15) {
["bookable_id"]=>
string(1) "3"
["event_date"]=>
string(10) "2020-09-15"
}
[6]=>
array(15) {
["bookable_id"]=>
string(1) "2"
["event_date"]=>
string(10) "2021-09-09"
}
}
This is my function:
function searchMatchingDates($compare, $array)
{
foreach ($array as $val) {
if ($compare["event_date"]== $val["event_date"]){
return $val;
}
}
return null;
And this is how i searched it:
foreach ($dateArray as $compare) {
$match = searchMatchingDates($compare, $array);
}
if($match){
echo "$compare['bookable_id'] + $match['bookable_id']; "
}
This works and return the date. It however return duplicate dates as the array will compare twice.
I need a way to remove an array once an array has been compared once .
For example, once array once has ran its iteration it needs to be removed so that the next array does not do a comparison on it.
If I understand the question, you want to return the dates which feature more than once in the array?
You could do this by counting all of those which feature more than once (array_count_values() https://www.php.net/manual/en/function.array-count-values.php combined with array_column()), then filtering the array based on that outcome.
// get dates which feature more than once
$dateCounts = array_filter(
array_count_values(array_column($dateArray, 'event_date')),
function ($count) {
return $count > 1;
}
);
// filter those matching dates
$matching = array_filter($dateArray, function ($date) use ($dateCounts) {
return isset($dateCounts[$date['event_date']]);
});
var_dump($matching);

Query gives one indexed array with many elements

I have code like this:
$ch = #new mysqli ($config['db']['host'],$config['db']['user'],$config['db']['password'],$config['db']['database']);
if($result = $ch->query("SELECT pid FROM posts"))
{
while($pids = $result->fetch_assoc())
{
var_dump($pids);
}
var_dump gives me:
array(1) { ["pid"]=> string(1) "1" } array(1) { ["pid"]=> string(1) "2" } array(1) { ["pid"]=> string(1) "3" } array(1) { ["pid"]=> string(1) "4" }
I have two problems:
In database column 'pid' is an int type but the query yields an array of strings
All records from database (4) are saved in one row in an array (got only one index)
Because of that I can't use max(), because it gives me all records (4321).
You have got 4. Check correctly. The var_dump() executes four times, returning a single array (column - row values):
array(1) {
["pid"]=> string(1) "1"
}
array(1) {
["pid"]=> string(1) "2"
}
array(1) {
["pid"]=> string(1) "3"
}
array(1) {
["pid"]=> string(1) "4"
}
If you want everything to be in a single variable, use:
$allPids = array();
while (false != ($pids = $result->fetch_assoc())) {
$allPids[] = $pids;
}
var_dump($allPids);
You need to store them in one array first.
while($pids = $result->fetch_assoc())
{
$array[] = $pids;
}
var_dump($array);
And for the data type PHP will cast them accordingly.

PHP: Combining data with a shared key from a single array into new array

I have this array:
array(5) {
[0]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[1]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
[2]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "3"
["productTxtVal"]=>
string(5) "Text3"
}
[3]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[4]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
}
With the above input, I want the output array to look like this:
array(2) {
[0]=>
array(3) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTxtVal"]=>
string(17) "Text1 Text2 Text3"
}
[1]=>
array(3) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTxtVal"]=>
string(11) "Text1 Text2"
}
}
The resulting array does not need the productTextSeq key, just the combined values of productTextVal, when the productCode is the same. I've searched SO for examples of this but it seems every example I've found are based on multiple input arrays. I know I can brute force this with nested foreach functions but would love a more elegant solution.
I ended up just doing it the brute force method, here is my solution if anyone's interested:
$productData = array();
$sortedData = array();
$comments = '';
$saveKey = '';
$appendComment = false;
$idx = 0;
foreach ($data as $key=>$value) {
foreach ($value as $k=>$v) {
if ($k == 'productCode') {
if ($v == $saveKey) {
$appendComment = true;
} else {
$appendComment = false;
$saveKey = $v;
if ($idx !== 0) { // Don't write to array on first iteration!
$productData['productTxtVal'] = $comments;
$sortedData[] = $productData;
}
}
}
if ($k == 'productTxtVal') {
if ($appendComment == true) {
$comments .= ' ' . trim($v);
} else {
$comments = trim($v);
}
}
}
$productData = $value;
$idx++;
}
Not "elegant" but it works. I also have a check after this logic in case only one productCode is in the original array, as it won't be written to the $sortedData array since the key never changes.
The following code assumes you control the contents of the original data array (due to risk of injection using extract() function) and that no 2 items with the same productCode have the same productTextSeq.
$products = [];
foreach ($data as $item) {
// extract contents of item array into variables
extract($item);
if (!isset($products[$productCode])) {
// create product array with code, upc, text as array
$products[$productCode] = compact('productCode', 'productUPC') + ['productTxtVal' => []];
}
// add text value to array with sequence as index
$products[$productCode]['productTxtVal'][$productTextSeq] = $productTxtVal;
}
$products = array_values( // ignore array keys
array_map(function($product) {
ksort($product['productTxtVal']); // sort text as array by index/ sequence
$product['productTxtVal'] = implode(' ', $product['productTxtVal']); // implode into string
return $product;
}, $products)
);
You can run the code here: https://repl.it/BWQL

Get value in PHP from JSON

I need to get the objects information for "label", "name" where value=true in a PHP variable and not were value=false.
How is this done with this JSON array?
If I make a var_dump of the JSON I get this:
array(8) {
[0]=>
object(stdClass)#8 (3) {
["label"]=>
string(4) "Name"
["name"]=>
string(7) "txtName"
["value"]=>
bool(true)
}
[1]=>
object(stdClass)#9 (3) {
["label"]=>
string(6) "E-mail"
["name"]=>
string(8) "txtEmail"
["value"]=>
bool(true)
}
[2]=>
object(stdClass)#10 (3) {
["label"]=>
string(12) "Phone Number"
["name"]=>
string(8) "txtPhone"
["value"]=>
bool(false)
}
[3]=>
object(stdClass)#11 (3) {
["label"]=>
string(19) "Mobile Phone Number"
["name"]=>
string(14) "txtMobilePhone"
["value"]=>
bool(false)
}
}
$arr = array();
$i = 0;
foreach($json as $key => $items) {
if($items->value == true) {
$arr[$i]['label'] = $items->label;
$arr[$i]['name'] = $items->name;
$i++;
}
}
You can decode it as an object or an array, in this example I use an array.
First you want to take the JSON encoded information and decode it into a PHP array, you can use json_decode() for this:
$data = json_decode($thejson,true);
//the Boolean argument is to have the function return an array rather than an object
Then you can loop through it as you would a normal array, and build a new array containing only elements where 'value' matches your needs:
foreach($data as $item) {
if($item['value'] == true) {
$result[] = $item;
}
}
You then have the array
$result
at your disposal.
Simplification of the suggestions proposed by users JohnnyFaldo and som:
$data = json_decode($thejson, true);
$result = array_filter($data, function($row) {
return $row['value'] == true;
});

Why does is_array() return false?

I have this SimpleXML object:
object(SimpleXMLElement)#176 (1) {
["record"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#39 (2) {
["f"]=>
array(2) {
[0]=>
string(13) "stuff"
[1]=>
string(1) "1"
}
}
[1]=>
object(SimpleXMLElement)#37 (2) {
["f"]=>
array(2) {
[0]=>
string(13) "more stuff"
[1]=>
string(3) "90"
}
}
}
Why does is_array($object->record) return false? It clearly says it's an array. Why can't I detect it using is_array?
Also, I am unable to cast it as an array using (array) $object->record. I get this error:
Warning: It is not yet possible to
assign complex types to properties
SimpleXML nodes are objects that can contain other SimpleXML nodes. Use iterator_to_array().
It's not an array. The var_dump output is misleading. Consider:
<?php
$string = <<<XML
<?xml version='1.0'?>
<foo>
<bar>a</bar>
<bar>b</bar>
</foo>
XML;
$xml = simplexml_load_string($string);
var_dump($xml);
var_dump($xml->bar);
?>
Output:
object(SimpleXMLElement)#1 (1) {
["bar"]=>
array(2) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
}
}
object(SimpleXMLElement)#2 (1) {
[0]=>
string(1) "a"
}
As you can see by the second var_dump, it is actually a SimpleXMLElement.
I solved the problem using count() function:
if( count( $xml ) > 1 ) {
// $xml is an array...
}

Categories