PHP Object Iteration - Nested Structures - php

I'm iterating over an array of objects, some of them nested in a non-uniform way. I'm doing the following:
foreach($response['devices'] as $key => $object) {
foreach($object as $key => $value) {
echo $key . " : " . "$value . "<br>";
}
}
Which works...until it hits the next embedded array/object, where it gives me an 'Notice: Array to string conversion in C:\xampp\htdocs\index.php on line 65' error
I'm relatively new to PHP and have thus far only had to deal with uniform objects. This output is far more unpredictable and can't be quantified in the same way. How can I 'walk' through the data so that it handles each array it comes across?

You should make a recusive function this means, the function call itself until a condition is met and then it returns the result and pass through the stack of previously called function to determine the end results. Like this
<?php
// associative array containing array, string and object
$array = ['hello' => 1, 'world' => [1,2,3], '!' => ['hello', 'world'], 5 => new Helloworld()];
// class helloworld
class Helloworld {
public $data;
function __construct() {
$this->data = "I'm an object data";
}
}
//function to read all type of data
function recursive($obj) {
if(is_array($obj) or is_object($obj)) {
echo ' [ '.PHP_EOL;
foreach($obj as $key => $value) {
echo $key.' => ';
recursive($value);
}
echo ' ] '.PHP_EOL;
} else {
echo $obj.PHP_EOL;
}
}
// call recursive
recursive($array);
?>
This prints something like this :
[
hello => 1
world => [
0 => 1
1 => 2
2 => 3
]
! => [
0 => hello
1 => world
]
5 => [
data => I'm an object data
]
]
I hope this helps ?

Related

PHP: How to create a good foreach shorthand?

I have a simple object (or array) like this...
stdClass Object (
[people] => Array
(
[0] => stdClass Object (
[name] => 'John',
[age] => 50,
)
[0] => stdClass Object (
[name] => 'Martin',
[age] => 47,
)
)
And I can easily loop through it using foreach like this
foreach ($people as $person) {
echo $person->name . '<br>';
}
But I would somehow like to have a shorter way to echo all names with something like this...
print_each($people->name)
And it would do exactly the same thing with only 1 short line of code as my 3 lines of foreach code did.
Is there a function like this or how would we go about creating a function like that?
You can use array_column and implode.
echo implode("<br>\n", array_column($arr, "name"));
Probably array_map is the closest to what you want.
array_map(function($person) { echo $person->name; }, $people);
Shortest way and not that ugly would be to add a
__toString
Method to the Person Object like this:
class Person {
public $name;
public function __toString()
{
return (string) $this->name;
}
}
This then enables you to use the very super short:
array_walk($people, 'printf');
Syntax.
If you have array, you can use array_column for that:
$people = [
['name' => 'John', 'age' => 3],
['name' => 'Carl', 'age' => 43]
];
var_dump(
array_column($people, 'name')
);
/*
array(2) {
[0]=>
string(4) "John"
[1]=>
string(4) "Carl"
}
Since PHP 7.4 you can do:
echo implode('', array_map(fn($person) => $person->name . '<br>', $people));
The inner array_map() function takes as second parameter your initial array $people.
The inner array_map() function takes as first parameter an arrow function fn() => that gets the single items $person out of your initial array $people
inside the arrow function each $person->name gets concated with '<br>' and written as value in a new array.
this new array will be returned by the array_map() function
The items of this array will be passed as second parameter to the implode() function and glued together with the empty string ''.
the entire string that implode() returns gets echoed out
If you want to get "smart" about it you can write something like this:
array_walk_recursive($a, function($v, $k) {echo $k === 'name' ? $v : '';});
But being smart over readability is a bad idea, always.
If I had to write a function to do that, it would be something along these lines:
function print_each($collection, $property) {
foreach ($collection as $item) {
echo $item->$property . "<br />";
}
}
Which could be used like so:
$people = [
(object)[
"name" => "Bob",
"age" => 25
],
(object)[
"name" => "Dan",
"age" => 31
],
(object)[
"name" => "Sally",
"age" => 45
]
];
print_each($people, "name"); // prints "Bob<br />Dan<br />Sally<br />"

How to do array push in object wise using PHP

I have one array, in this array values, i want to push object wise,how can do this?
print_r($_POST['amenity_check']);
Array
(
[0] => Gym
[1] => Swimming Pool
)
Expected Results
"amenities": [
{
"amenity_name":"Gym"
},
{
"amenity_name":"Swimming Pool"
}
],
]
You can try the following:
$output = [];
foreach ($_POST['amenity_check'] as $value)
{
$output[] = [
'amenity_name' => $value
];
}
echo json_encode([
"amenities" => $output
]);
Output:
{"amenities":[{"amenity_name":"Gym"},{"amenity_name":"Swimming Pool"}]}
This uses a foreach loop to get the desired output as array, and the uses json_encode to turn it into a json string.

search multidimensional array with mixed data types, echo back result

I have a php array with mixed data types (arrays, ints, strings). I want to search the array for a match contained within an array of mixed data types as show below.
my test array
$arrActors =[0 => [
'actorName' => "heath ledger",
'actorAlias' => [],
'actorGender' => 1,
'actorNoms' => ["angel", "john constantine"]
],
1 => [
'actorName' => "Michael pare",
'actorAlias' => ["mikey", "that guy"],
'actorGender' => 1,
'actorNoms' => ["cyclops", "slim", "eric the red"]
]
];
If the needle is set to an element and that element is found to exists in actorNoms, I want to echo back the name of the associated actor (actorName). In the below example, I have attempted to find cyclops (actorNoms) return the name of the actor, Michael Pare (actorName) who is associated with him.
My Attempt to find actorNoms and return the actors name
$needle = 'cyclops';
foreach($arrActors as $haystack)
{
if(in_array($needle, $haystack)) {
echo $haystack['actorNoms'] . '<br />' ;
}else{
echo 'nothing found<br />';//echo something so i know it ran
}
}
My attempt returns fails as it echo's 'nothing found'. How do I echo back the name of the actor Michael Pare when searching for cyclops.
Thank you for any help given. I have tried to format my code correctly for ease of use. I have searched Stack, Google and other sources for several hours now trying to find a solution I can understand. I am not very adept, but I promise I am learning and all help is appreciated.
Instead of using
if(in_array($needle, $haystack)) {
echo $haystack['actorNoms'] . '<br />' ;
}
try this:
if(in_array($needle, $haystack['actorNoms'])) {
echo $haystack['actorName'] . '<br />' ;
}
what you did was search the $haystack which is the main array for the actors.
in_array doesn't search nested arrays automatically for multidimensional arrays, hence you need to specify the area in which you would search: in_array($haystack['actorNoms'])
$needle = 'cyclops';
foreach($arrActors as $haystack)
{
if(in_array($needle, $haystack['actorNoms'])) {
echo $haystack['actorName'] . '<br />' ;
}
}
in_array, works for one level array only. So every time it goes through first level array, where as 'actorNoms' is sub array under firstlevel array.
Try this this give you parent index using this index you will get the data
$arrActors = array( array(
'actorName' => "heath ledger",
'actorAlias' => array(),
'actorGender' => 1,
'actorNoms' => array("angel", "john constantine")
),array(
'actorName' => "Michael pare",
'actorAlias' => array("mikey", "that guy"),
'actorGender' => 1,
'actorNoms' => array("cyclops", "slim", "eric the red")
)
);
print_r( getParent_id("cyclops",$arrActors));
function getParent_id($child, $stack) {
foreach ($stack as $k => $v) {
if (is_array($v)) {
// If the current element of the array is an array, recurse it and capture the return
$return = getParent_id($child, $v);
// If the return is an array, stack it and return it
if (is_array($return)) {
return array($k => $return);
}
} else {
// Since we are not on an array, compare directly
if (preg_match("/$child/",$v)) {
// And if we match, stack it and return it
return array($k => $child);
}
}
}
// Return false since there was nothing found
return false;
}

How to access data in nested Std Object array in PHP

I need to access the data: 'hotelID', 'name', 'address1','city' etc. I have the following Std Object array ($the_obj) in PHP that contains the following data:
object(stdClass)[1]
public 'HotelListResponse' =>
object(stdClass)[2]
public 'customerSessionId' => string '0ABAAA87-6BDD-6F91-4292-7F90AF49146E' (length=36)
public 'numberOfRoomsRequested' => int 0
public 'moreResultsAvailable' => boolean false
public 'HotelList' =>
object(stdClass)[3]
public '#size' => string '227' (length=3)
public '#activePropertyCount' => string '227' (length=3)
public 'HotelSummary' =>
array (size=227)
0 =>
object(stdClass)[4]
public 'hotelId' => 112304
public 'name' => La Quinta Inn and Suites Seattle Downtown
public 'address1' => 2224 8th Ave
public 'city' => Seattle
public 'stateProvinceCode' => WA
public 'postalCode' => 98121
public 'countryCode' => US
public 'airportCode' => SEA
public 'propertyCategory' => 1
public 'hotelRating' => 2.5
I have tried the following for lets say to access the 'name':
echo $the_obj->HotelListResponse->HotelList->HotelSummary[0]->name;
Also I have tried to print each key and value pairs by using foreach loop but I keep on getting errors. Here is what I tried:
foreach ($the_obj->HotelListResponse->HotelList->HotelSummary[0] as $key => $value){
echo $key.' : '.$value.'<br />';
}
Here are the errors that I get:
Trying to get property of non-object
Warning: Invalid argument supplied for foreach()
Thank you everyone for answering, I have figured out the way to access the 'hotelID', 'name' and all other keys and value pairs in the deepest nest of the array.
I converted the Std Object array to an associative array, then I accessed each of the value by using the foreach loop:
foreach ($the_obj["HotelListResponse"]["HotelList"]["HotelSummary"] as $value){
echo $value["hotelId"];
echo $value["name"];
//and all other values can be accessed
}
To access both (Keys as well as values):
foreach ($the_obj["HotelListResponse"]["HotelList"]["HotelSummary"] as $key=>$value){
echo $key.'=>'.$value["hotelId"];
echo $key.'=>'.$value["name"];
//and all other keys as well as values can be accessed
}
Regarding to #Satya's answer I'd like to show simpler way for Object to array conversion, by using json functions:
$obj = ...
$tmp = json_encode($obj);
$objToArray = json_decode($tmp,true);
This way you can easily access array items. First you can dump structure...
try something like this :
$p=objectToArray($result);
recurse($p);
}
function objectToArray( $object )
{
if( !is_object( $object ) && !is_array( $object ) )
{
return $object;
}
if( is_object( $object ) )
{
$object = get_object_vars( $object );
}
return array_map( 'objectToArray', $object );
}
function recurse ($array)
{
//statements
foreach ($array as $key => $value)
{
# code...
if( is_array( $value ) )
{
recurse( $value );
}
else
{ $v=$value;
$v=str_replace("’",'\'',strip_tags($v));
$v=str_replace("–",'-',$v);
$v=str_replace("‘",'\'',strip_tags($v));
$v=str_replace("“",'"',strip_tags($v));
$v=str_replace("”",'"',strip_tags($v));
$v=str_replace("–",'-',strip_tags($v));
$v=str_replace("’",'\'',strip_tags($v));
$v=str_replace("'",'\'',strip_tags($v));
$v=str_replace(" ",'',strip_tags($v));
$v=html_entity_decode($v);
$v=str_replace("&",' and ',$v);
$v = preg_replace('/\s+/', ' ', $v);
if($key=="image")
{
if(strlen($v)==0)
{
echo '<'.$key .'>NA</'.$key.'>';
}
else
{
echo '<'.$key .'>'. trim($v) .'</'.$key.'>';
}
}
}
}
}

Getting JSON data in PHP

I have a JSON data like this:
{
"hello":
{
"first":"firstvalue",
"second":"secondvalue"
},
"hello2":
{
"first2":"firstvalue2",
"second2":"secondvalue2"
}
}
I know how to retrieve data from object "first" (firstvalue) and second (secondvalue) but I would like to loop trough this object and as a result get values: "hello" and "hello2"...
This is my PHP code:
<?php
$jsonData='{"hello":{"first":"firstvalue","second":"secondvalue"},"hello2":{"first2":"firstvalue2","second2":"secondvalue2"}}';
$jsonData=stripslashes($jsonData);
$obj = json_decode($jsonData);
echo $obj->{"hello"}->{"first"}; //result: "firstvalue"
?>
Can it be done?
The JSON, after being decoded, should get you this kind of object :
object(stdClass)[1]
public 'hello' =>
object(stdClass)[2]
public 'first' => string 'firstvalue' (length=10)
public 'second' => string 'secondvalue' (length=11)
public 'hello2' =>
object(stdClass)[3]
public 'first2' => string 'firstvalue2' (length=11)
public 'second2' => string 'secondvalue2' (length=12)
(You can use var_dump($obj); to get that)
i.e. you're getting an object, with hello and hello2 as properties names.
Which means this code :
$jsonData=<<<JSON
{
"hello":
{
"first":"firstvalue",
"second":"secondvalue"
},
"hello2":
{
"first2":"firstvalue2",
"second2":"secondvalue2"
}
}
JSON;
$obj = json_decode($jsonData);
foreach ($obj as $name => $value) {
echo $name . '<br />';
}
Will get you :
hello
hello2
This will work because foreach can be used to iterate over the properties of an object -- see Object Iteration, about that.

Categories