php stdClass to array - php

I have a problem to convert an object stdClass to array.
I have tried in this way:
return (array) $booking;
or
return (array) json_decode($booking,true);
or
return (array) json_decode($booking);
The array before the cast is full with one record, after my try to cast it is empty.
How to cast / convert it without delete its rows?
array before cast:
array(1) { [0]=> object(stdClass)#23 (36) { ["id"]=> string(1) "2" ["name"]=> string(0) "" ["code"]=> string(5) "56/13" } }
after cast is empty NULL if I try to make a var_dump($booking);
I have also tried this function but always empty:
public function objectToArray($d) {
if (is_object($d)) {
// Gets the properties of the given object
// with get_object_vars function
$d = get_object_vars($d);
}
if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return array_map(__FUNCTION__, $d);
}
else {
// Return array
return $d;
}
}

The lazy one-liner method
You can do this in a one liner using the JSON methods if you're willing to lose a tiny bit of performance (though some have reported it being faster than iterating through the objects recursively - most likely because PHP is slow at calling functions). "But I already did this" you say. Not exactly - you used json_decode on the array, but you need to encode it with json_encode first.
Requirements
The json_encode and json_decode methods. These are automatically bundled in PHP 5.2.0 and up. If you use any older version there's also a PECL library (that said, in that case you should really update your PHP installation. Support for 5.1 stopped in 2006.)
Converting an array/stdClass -> stdClass
$stdClass = json_decode(json_encode($booking));
Converting an array/stdClass -> array
The manual specifies the second argument of json_decode as:
assoc
When TRUE, returned objects will be converted into associative arrays.
Hence the following line will convert your entire object into an array:
$array = json_decode(json_encode($booking), true);

use this function to get a standard array back of the type you are after...
return get_object_vars($booking);

Use the built in type cast functionality, simply type
$realArray = (array)$stdClass;

Since it's an array before you cast it, casting it makes no sense.
You may want a recursive cast, which would look something like this:
function arrayCastRecursive($array)
{
if (is_array($array)) {
foreach ($array as $key => $value) {
if (is_array($value)) {
$array[$key] = arrayCastRecursive($value);
}
if ($value instanceof stdClass) {
$array[$key] = arrayCastRecursive((array)$value);
}
}
}
if ($array instanceof stdClass) {
return arrayCastRecursive((array)$array);
}
return $array;
}
Usage:
$obj = new stdClass;
$obj->aaa = 'asdf';
$obj->bbb = 'adsf43';
$arr = array('asdf', array($obj, 3));
var_dump($arr);
$arr = arrayCastRecursive($arr);
var_dump($arr);
Result before:
array
0 => string 'asdf' (length = 4)
1 =>
array
0 =>
object(stdClass)[1]
public 'aaa' => string 'asdf' (length = 4)
public 'bbb' => string 'adsf43' (length = 6)
1 => int 3
Result after:
array
0 => string 'asdf' (length = 4)
1 =>
array
0 =>
array
'aaa' => string 'asdf' (length = 4)
'bbb' => string 'adsf43' (length = 6)
1 => int 3
Note:
Tested and working with complex arrays where a stdClass object can contain other stdClass objects.

This function worked for me:
function cvf_convert_object_to_array($data) {
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
return array_map(__FUNCTION__, $data);
}
else {
return $data;
}
}
Reference: http://carlofontanos.com/convert-stdclass-object-to-array-in-php/

Please use following php function to convert php stdClass to array
get_object_vars($data)

Just googled it, and found here a handy function that is useful for converting stdClass object to array recursively.
<?php
function object_to_array($object) {
if (is_object($object)) {
return array_map(__FUNCTION__, get_object_vars($object));
} else if (is_array($object)) {
return array_map(__FUNCTION__, $object);
} else {
return $object;
}
}
?>
EDIT: I updated this answer with content from linked source (which is also changed now), thanks to mason81 for suggesting me.

Here's how I use it in Laravel without Eloquent.
function getUsers(){
$users = DB::select('select * from users');
$data = json_decode(json_encode($users), true); // to array
return view('page')->with('data', $data);
}

Here is a version of Carlo's answer that can be used in a class:
class Formatter
{
public function objectToArray($data)
{
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
return array_map(array($this, 'objectToArray'), $data);
}
return $data;
}
}

The following code will read all emails & print the Subject, Body & Date.
<?php
$imap=imap_open("Mailbox","Email Address","Password");
if($imap){$fixMessages=1+imap_num_msg($imap); //Check no.of.msgs
/*
By adding 1 to "imap_num_msg($imap)" & starting at $count=1
the "Start" & "End" non-messages are ignored
*/
for ($count=1; $count<$fixMessages; $count++){
$objectOverview=imap_fetch_overview($imap,$count,0);
print '<br>$objectOverview: '; print_r($objectOverview);
print '<br>objectSubject ='.($objectOverview[0]->subject));
print '<br>objectDate ='.($objectOverview[0]->date);
$bodyMessage=imap_fetchbody($imap,$count,1);
print '<br>bodyMessage ='.$bodyMessage.'<br><br>';
} //for ($count=1; $count<$fixMessages; $count++)
} //if($imap)
imap_close($imap);
?>
This outputs the following:
$objectOverview: Array ( [0] => stdClass Object ( [subject] => Hello
[from] => Email Address [to] => Email Address [date] => Sun, 16 Jul 2017 20:23:18 +0100
[message_id] => [size] => 741 [uid] => 2 [msgno] => 2 [recent] => 0 [flagged] => 0
[answered] => 0 [deleted] => 0 [seen] => 1 [draft] => 0 [udate] => 1500232998 ) )
objectSubject =Hello
objectDate =Sun, 16 Jul 2017 20:23:18 +0100
bodyMessage =Test
Having struggled with various suggestions I have used trial & error to come up with this solution. Hope it helps.

Here is the best Object to Array function I have - works recursively:
function object_to_array($obj, &$arr){
if(!is_object($obj) && !is_array($obj)){
$arr = $obj;
return $arr;
}
foreach ($obj as $key => $value) {
if (!empty($value)) {
$arr[$key] = array();
object_to_array_v2($value, $arr[$key]);
} else {
$arr[$key] = $value;
}
}
return $arr;
}
$clean_array = object_to_array($object_data_here);

Related

Recursive function only works for first level of array

I wrote a recursive function which relies on echo to work, and it works perfectly. But, to challenge myself, I wanted to make it return an array of processed values instead of echoing the values directly.
printAll(
json_decode('[{"id":1,"children":[{"id":2},{"id":5,"children":[{"id":3}]}]},{"id":4}]', true)
);
function printAll($a, $level = '', $values = []) {
foreach($a as $v) {
$values[] = $value = "{$level}{$v['id']}";
if(!empty($v['children'])) {
return printAll($v['children'], "{$value}.", $values);
}
}
return $values;
}
But I'm getting unexpected results. This function currently returns an array that looks like this:
Array
(
[0] => 1
[1] => 1.2
[2] => 1.5
[3] => 1.5.3
)
But in this case, I'm expecting this:
Array
(
[0] => 1
[1] => 1.2
[2] => 1.5
[3] => 1.5.3
[4] => 4
)
It looks like my recursive function only processes the very first value of $data and all of it's children, but never the rest of $data. I'm assuming this is because I am using return which ends the loop.
My question is, how can I make my printAll() function process the entire set of data, without overly complicating the function?
The problem is that as you have
return printAll($v['children'], "{$value}.", $values);
part of the way through, this will ignore any further items in subsequent elements.
A quick fix would be to just add the new values into the current values and have the 1 return at the end of the routine...
$values += printAll($v['children'], "{$value}.", $values);
You need to remove the return printAll(...) and add the value to the variable. Otherwise it will stop in the first value that has a 'children'
<?php
function printAll($a, $level = '', $values = []) {
foreach($a as $v) {
$values[] = $value = "{$level}{$v['id']}";
if(!empty($v['children'])) {
//Just remove this return and add to the variable you already have.
$values = printAll($v['children'], "{$value}.", $values);
}
}
return $values;
}
$a = json_decode('[{"id":1,"children":[{"id":2},{"id":5,"children":[{"id":3}]}]},{"id":4}]',true);
var_dump(printAll($a));

add properties to php pbject

I have this object that represents colors with counts
I am trying to add property of color code to the object from another array
printing object $oColors :
stdClass Object
(
[black] => 2207
[blue] => 783
[red] => 672
[white] => 555
[green] => 463
)
and am trying to loop through them and map them with another array of objects like below :
foreach ($oColors as $color => $count) {
if (array_key_exists($color, $oColorsMapper)) {
$oColors->$color['code']= $oColorsMapper->$color->code;
}
}
but printing the result is showing the object is still the same
what am I doing wrong thanks
The problem is that the keys are not arrays. They are strings. So the solution would be something like:
foreach ($oColors as $color => $count) {
if (array_key_exists($color, $oColorsMapper)) {
$oColors->$color = array(
'count' => $count,
'code' => $oColorsMapper->$color->code
);
}
}
As a simple example:
$arr = (object) array('test' => 43, 'test1' => 435);
function test($obj) {
foreach ($obj as $key => $val) {
$obj->$key = array($val);
}
}
test($arr);
var_dump($arr);
will output:
object(stdClass)#1 (2) {
["test"]=>
array(1) {
[0]=>
int(43)
}
["test1"]=>
array(1) {
[0]=>
int(435)
}
}
#sisimh
Your problem is passing variable into function without reference.
By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference. More info u can get here
So, if you have function:
function changeColors ($oColors) {
...
}
You should change $oColors to &$oColors, like this:
function changeColors (&$oColors) {
Next point is that $color from your example with foreach section is not an array. It'a a key value (in most cases it has a string type). Perhabs, you made mistake and ['code'] should be absent.
Another point of my attention is array_key_exists. In most cases better to use isset instead of array_key_exists. It's a more faster way.
For example:
function changeColors (&$oColors) {
...
foreach ($oColors as $color => $count) {
if (isset($oColorsMapper->$color)) {
$oColors->$color = $oColorsMapper->$color->code;
}
}
...
}

How to find object in php array and delete it?

Here is print_r output of my array:
Array
(
[0] => stdClass Object
(
[itemId] => 560639000019
[name] => Item no1
[code] => 00001
[qty] => 5
[id] => 2
)
[1] => stdClass Object
(
[itemId] => 470639763471
[name] => Second item
[code] => 76347
[qty] => 9
[id] => 4
)
[2] => stdClass Object
(
[itemId] => 56939399632
[name] => Item no 3
[code] => 39963
[qty] => 6
[id] => 7
)
)
How can I find index of object with [id] => 4 in order to remove it from array?
$found = false;
foreach($values as $key => $value) {
if ($value->id == 4) {
$found = true;
break;
}
}
if ($found) unset($values[$key]);
This is considered to be faster then any other solution since we only iterate the array to until we find the object we want to remove.
Note: You should not remove an element of an array while iterating so we do it afterwards here.
foreach($parentObj AS $key=>$element){
if ($element->id == THE_ID_YOU_ARE_LOOKING_FOR){
echo "Gottcha! The index is - ". $key;
}
}
$parentObj is obviously your root array - the one that holds all the others.
We use the foreach loop to iterate over each item and then test it's id property against what ever value you desire. Once we have that - the $key that we are on is the index you are looking for.
use array_search:
$a = new stdClass;
$b = new stdClass;
$a->id = 1;
$b->id = 2;
$arr = array($a, $b);
$index = array_search($b, $arr);
echo $index;
// prints out 1
try this
foreach($array AS $key=>$object){
if($object['id'] == 4){
$key_in_array = $key;
}
}
// chop it from the original array
array_slice($array, $key_in_array, 1);
Another way to achieve the result is to use array_filter.
$array = array(
(object)array('id' => 5),
(object)array('id' => 4),
(object)array('id' => 3)
);
$array = array_filter($array, function($item) {
return $item->id != 4;
});
print_r($array);
Here's my solution. Given, it is a bit hackish, but it will get the job done.
search(array $items, mixed $id[, &$key]);
Returns the item that was found by $id. If you add the variable $key it will give you the key of the item found.
function search($items, $id, &$key = null) {
foreach( $items as $item ) {
if( $item->id == $id ) {
$key = key($item);
return $item;
break;
}
}
return null;
}
Usage
$item = search($items, 4, $key);
unset($items[$key]);
Note: This could be modified to allow a custom key and return multiple items that share the same value.
I've created an example so you can see it in action.
A funny alternative
$getIdUnset = function($id) use ($myArray)
{
foreach($myArray as $key => $obj) {
if ($obj->id == $id) {
return $key;
}
}
return false;
};
if ($unset = $getIdUnset(4)) {
unset($myArray[$unset]);
}
Currently php does not have any supported function for this yet.
So refer to Java's Vector, or jQuery's $.inArray(), it would simply be:
public function indexOf($object, array $elementData) {
$elementCount = count($elementData);
for ($i = 0 ; $i < $elementCount ; $i++){
if ($object == $elementData[$i]) {
return $i;
}
}
return -1;
}
You can save this function as a core function for later.
In my case, this my array as $array
I was confused about this problem of my project, but some answer here helped me.
array(3) {
[0]=> float(-0.12459619130796)
[1]=> float(-0.64018439966448)
[2]=> float(0)
}
Then use if condition to stop looping
foreach($array as $key => $val){
if($key == 0){ //the key is 0
echo $key; //find the key
echo $val; //get the value
}
}
I know, after so many years this could be a useless answer, but why not?
This is my personal implementation of a possible index_of using the same code as other answers but let the programmer to choose when and how the check will be done, supporting also complex checks.
if (!function_exists('index_of'))
{
/**
* #param iterable $haystack
* #param callable $callback
* #param mixed|null &$item
* #return false|int|string
*/
function index_of($haystack, $callback, &$item = null)
{
foreach($haystack as $_key => $_item) {
if ($callback($_item, $_key) === true) {
$item = $_item;
return $_key;
}
}
return false;
}
}
foreach( $arr as $k=>&$a) {
if( $a['id'] == 4 )
unset($arr[$k]);
}

Accessing a PHP array

I'm sure this has been asked before, but I can't seem to find the answer.
To that end, I have an array that looks like this:
Array
(
[0] => Array
(
[status] => active
[sid] => 1
)
[1] => Array
(
[status] => expired
[sid] => 2
)
)
What I'd like to be able to do is type $arrayName["active"] and it return the SID code. I will be using this like a dictionary object of sorts. It's like I need to reindex the array so that it is the key/value pair that I need. I was just wondering if there was an easier way to do it.
You should convert your nested arrays into a single associative array. Something like this should take your example and turn it into an associative array:
$assoc_array = array();
foreach( $example_array as $values ) {
$assoc_array[$values["status"]] = $values["sid"];
}
You can then access the sid for a given status by using $assoc_array["expired"] (returns 2)
After seeing the others' solutions, I realize this might be bit of an overkill, but I'm still just gonna throw it out there:
$foo = array(
array('status' => 'active', 'sid' => 1),
array('status' => 'expired', 'sid' => 2),
);
// Get all the 'status' elements of each subarray
$keys = array_map(function($element) {
return $element['status'];
}, $foo);
// Get all the 'sid' elements of each subarray
$values = array_map(function($element) {
return $element['sid'];
}, $foo);
// Combine them into a single array, with keys from one and values from another
$bar = array_combine($keys, $values);
print_r($bar);
Which prints:
Array
(
[active] => 1
[expired] => 2
)
Manual pages:
array_map()
array_keys()
array_values()
array_combine()
Anonymous functions
You can use this function:
function findActive($my_array){
foreach($my_array as $array){
foreach($array as $val){
if($val['status']==='active'){
return $val['sid'];
}
}
}
return false;
}
access it via a loop or directly.
if($arrayName[0]['status'] == "active") {
echo $arrayName[0]['sid'];
}
If you want to check all the SIDs
foreach($arrayName as $item) {
if($item['status'] == "active") {
echo $item['sid'];
}
}
A more direct approach is just putting the loop in a function and return an array of all active session IDs
$sidArr = array();
foreach($yourArr as $val) {
if("active" == $val["status"]) {
array_push($sidArr, $val["sid"]);
}
}
reindex would be the best
$arrayName = array()
foreach ($data_array as $data)
$arrayName[$data['status']]=$data['sid'];
Or use a function
function get_sid($status)
{
global $data_array;
foreach ($data_array as $data) {
if ($data['status']==$status)
return $data['sid'];
}
return false;
}

How to unset elements using array_walk_recursive

I need to unset elements from arrays that are nested into another array, in a way that only the first N elements would be kept (N being predefined). Only elements that have a numerical index should be affected.
Input array:
Array
(
[0] => Array (
[a] => 'w'
[b] => Array (
[0]=> 'x'
[1]=> 'x'
[2]=> 'x'
)
)
[1] => Array (
[a] => 'y'
)
[2] => Array (
[0] => 'z'
[1] => 'z'
[2] => 'z'
)
)
Desired output (with N=2):
Array
(
[0] => Array (
[a] => 'w'
[b] => Array (
[0]=> 'x'
[1]=> 'x'
)
)
[1] => Array (
[a] => 'y'
)
)
Based on the above definition, only [0][b][2] and [2] got unset because they had a numerical index and because they both represnted the 3rd element of their respective array.
Haven't tested but something like this might work.
function myFunc(&$array){
foreach($array as $key=>&$value){
if(is_array($value)){
myFunc($value);
}
if(is_numeric($key) && $key > 1){
unset($array[$key]);
}
}
}
About array_walk. php.net says:
the programmer cannot add, unset or
reorder elements. If the callback does
not respect this requirement, the
behavior of this function is
undefined, and unpredictable.
Write yourself a function that does exactly what you want. Then document the function so if you need to use it in about two weeks, you might want to know what exactly that function is doing.
I say this because the data structure you want to handle seems to be very specific. So it's worth to encapsulate it in a function on it's own to hide away the complexity. Name the function properly.
Inside the function you can process the data in the various ways and with the various conditions you need to formulate. Parameters from the outside can be passed as function parameters. The return value is the result you aim to achieve.
This worked for me, perhaps not the cleanest code.
$array = array
(
array(
'a' => 'w',
'b' => array('x','x','x')
),
array(
'a' => 'y'
),
array(
'z','z','z'
)
);
function recurse_and_strip ($array, &$size=2)
{
foreach ($array as $key => &$element)
{
if (is_hash($element))
{
$element = recurse_and_strip($element,$size);
} else if (is_array($element))
{
$deletefrom = false;
// now the tricky part.. see how many must be deleted
for ($i=0; $i < count($element); $i++ )
{
if ($size == 0)
{
echo "Delete from " . $i;
$deletefrom = $i;
break 1;
}
$size--;
}
if ($deletefrom !== false)
{
if ($deletefrom == 0)
{
unset($array[$key]);
} else {
array_splice($element,$deletefrom);
}
}
}
}
return $array;
}
// source http://www.benjaminkeen.com/?p=23
function is_hash($var)
{
if (!is_array($var))
return false;
return array_keys($var) !== range(0,sizeof($var)-1);
}
var_dump(recurse_and_strip($array,2));
array_walk_recursive itself cannot achieve what you want. Even though you can pass array by reference, unsetting the variable in the callback will only unset it in that scope.
However, you can use walk_recursive_remove function:
/**
* http://uk1.php.net/array_walk_recursive implementation that is used to remove nodes from the array.
*
* #param array The input array.
* #param callable $callback Function must return boolean value indicating whether to remove the node.
* #return array
*/
function walk_recursive_remove (array $array, callable $callback) {
foreach ($array as $k => $v) {
if (is_array($v)) {
$array[$k] = walk_recursive_remove($v, $callback);
} else {
if ($callback($v, $k)) {
unset($array[$k]);
}
}
}
return $array;
}
You will need to implement your own logic using the $callback to unset the specific values.
Here's a more general solution to modifying the array to which the leaf belongs. You can unset the current key, or add siblings, etc.
/**
* Modified version of array_walk_recursive that passes in the array to the callback
* The callback can modify the array or value by specifying a reference for the parameter.
*
* #param array The input array.
* #param callable $callback($value, $key, $array)
*/
function array_walk_recursive_array(array &$array, callable $callback) {
foreach ($array as $k => &$v) {
if (is_array($v)) {
array_walk_recursive_array($v, $callback);
} else {
$callback($v, $k, $array);
}
}
}

Categories