First, I have tried to find solution within the source here but couldn't find what I am looking so posting as a new question. Thanks for your help
I want to convert Array to Object. Here is what I am getting output
Array
(
[0] => stdClass Object
(
[id] => 1
[username] => robustsolver
[first_name] => John
[last_name] => Smith
)
[1] => stdClass Object
(
[id] => 2
[username] => pickypacker
[first_name] => Peter
[last_name] => Packer
)
)
So if I want any column for all users than I have to write code $users[0]->first_name; which gives me only one item. But what I am looking is to use $users->first_name and this should return an array of all user's column (here is first_name)
Hope I have explain in better way. :S
You can try this where $arr is your array:
function filter_callback($element) {
return $element->first_name;
}
$result= array_map('filter_callback', $arr);
From a quick test, this seems to work. It keeps objects of the array without your wanted property but its value is set to NULL. Not sure if that's what you want but you can edit the filter_callback to remove such elements.
Maybe something like this will work (not tested):
$arr = array(...); // array of objects (in)
$obj = new Object; // object of arrays (out)
foreach($arr as $a) {
foreach(get_object_vars($a) as $k=>$v) {
if(!property_exists($obj, $k)) {
$obj->{$k} = array();
}
$obj->{$k}[] = $v;
}
}
consider defining a new class:
class User_objects
{
public $first_name;
public $username;
public $last_name;
public function __construct()
{
$this->first_name = array();
$this->username = array();
$this->last_name = array();
}
}
then:
consider $array_of_objects to be your array of objects (input).
$users = new User_objects();
foreach ($array_of_objects as $object)
{
$users->first_name[] = $object->first_name; // append to array
$users->last_name[] = $object->last_name;
$users->username[] = $object->username;
}
then you can get your array from $users->first_name
You can write a simple helper function that will aid in the columns you wish to select:
function prop_selector($prop)
{
return function($item) use ($prop) {
return $item->{$prop};
};
}
$first_names = array_map(prop_selector('first_name'), $users);
$last_names = array_map(prop_selector('last_name'), $users);
Related
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));
This is a typical array structure:
$s = array ('etc'=>'etc', 'fields' =>
array (
0 => array (
'name'=>'year', 'description'=>'Year of ...', 'type'=>'integer',
),
1 => array (
'name'=>'label', 'description'=>'Offical short name', type'=>'string',
),
2 => array (
'name' => 'xx', 'description' => 'Xx ...', 'type' => 'string',
)
));
Here is a non-elegant way (or "not so elegant way") to reduce the big array to a simple array containing just one column:
$fields = array();
foreach ($strut['resources'][0]['schema']['fields'] as $r)
$fields[] = $r['name'];
This works, but is it possible to do the same with only one instruction? Perhaps using like array_reduce(), but I not see how.
Here are other typical "elegance PHP problem":
$fieldsByName = array();
foreach ($strut['resources'][0]['schema']['fields'] as $r)
$fields[$r['name']] = array(
'description' =>$r['description'],
'type' =>$r['type']
);
Is there a PHP alternative? The idea here is to use the keyword (name in the example) as an array key, and the other elements as usual fields, so, the generic non-elegant algorithm is
$fieldsByName = array();
foreach ($strut['resources'][0]['schema']['fields'] as $r){
$key = $r['name'];
unset($r['name']);
$fields[$key] = $r;
}
You can use array_column to extract all values with key name into another array
$names = array_column($strut['resources'][0]['schema']['fields'], 'name');
you could put your array thru this function:
function flatten(array $array) {
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
it will result in just a literal sequence of just values of your multidimensional array, like so.
Array
(
[0] => etc
[1] => year
[2] => Year of ...
[3] => integer
[4] => day
[5] => Day of the ...
[6] => string
[7] => xx
[8] => Xx ...
[9] => string
)
then, as you know original structure - you can parse this how needed. 4ex: every third value could be new assoc array's key value that holds an array with arrays of first two values.., or as you wish
array_column is first logical announcement, no surprises there.
Depending on how normalized your data is and how often this issues comes up, you could implement a class around your data. You can use the ArrayAccess, Iterator and Countable to make the change completely transparent, and you would be able to implement helper methods to hide the complexity of fetching data.
Here is an example, just using ArrayAccess:
class Strut implements ArrayAccess {
private $data;
private $fieldsByName = null;
public function __construct($data) {
$this->data = $data;
}
public function fieldsByName() {
//If the result has not already been computed
if($this->fieldsByName === null) {
$this->fieldsByName = array();
foreach($this->data['resources'][0]['schema']['fields'] as $r) {
$this->fieldsByName[ $r['name'] ] = array(
'description' =>$r['description'],
'type' =>$r['type']
);
}
}
return $this->fieldsByName;
}
/**
* ArrayAccess Methods
*/
public function offsetSet($offset, $value) {
$this->data[$offset] = $value;
}
public function offsetExists($offset) {
return isset( $this->data[$offset] );
}
public function offsetUnset($offset) {
unset( $this->data[$offset] );
}
public function offsetGet($offset) {
return isset( $this->data[$offset] ) ? $this->data[$offset] : null;
}
}
Using the above code you should be able to access your data just has you have been, but you also have the option of defining additional accessors in a nice container. Note that you also have to implement the Iterator interface to be able to foreach over your data.
This doesn't address the "elegance" issue of the underlying implementation (the other solutions do a nice job of that), but this way hides the complexity completely.
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);
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;
}
Suppose I have an array in PHP that looks like this
array
(
array(0)
(
array(0)
(
.
.
.
)
.
.
array(10)
(
..
)
)
.
.
.
array(n)
(
array(0)
(
)
)
)
And I need all the leaf elements of this mulit-dimensional array into a linear array, how should I go about doing this without resorting recursion, such like this?
function getChild($element)
{
foreach($element as $e)
{
if (is_array($e)
{
getChild($e);
}
}
}
Note: code snippet above, horribly incompleted
Update: example of array
Array
(
[0] => Array
(
[0] => Array
(
[0] => Seller Object
(
[credits:private] => 5000000
[balance:private] => 4998970
[queueid:private] => 0
[sellerid:private] => 2
[dateTime:private] => 2009-07-25 17:53:10
)
)
)
...snipped.
[2] => Array
(
[0] => Array
(
[0] => Seller Object
(
[credits:private] => 10000000
[balance:private] => 9997940
[queueid:private] => 135
[sellerid:private] => 234
[dateTime:private] => 2009-07-14 23:36:00
)
)
....snipped....
)
)
Actually, there is a single function that will do the trick, check the manual page at: http://php.net/manual/en/function.array-walk-recursive.php
Quick snippet adapted from the page:
$data = array('test' => array('deeper' => array('last' => 'foo'), 'bar'), 'baz');
var_dump($data);
function printValue($value, $key, $userData)
{
//echo "$value\n";
$userData[] = $value;
}
$result = new ArrayObject();
array_walk_recursive($data, 'printValue', $result);
var_dump($result);
You could use iterators, for example:
$result = array();
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY) as $value) {
$result[] = $value;
}
Use a stack:
<?php
$data = array(array(array("foo"),"bar"),"baz");
$results = array();
$process = $data;
while (count($process) > 0) {
$current = array_pop($process);
if (is_array($current)) {
// Using a loop for clarity. You could use array_merge() here.
foreach ($current as $item) {
// As an optimization you could add "flat" items directly to the results array here.
array_push($process, $item);
}
} else {
array_push($results, $current);
}
}
print_r($results);
Output:
Array
(
[0] => baz
[1] => bar
[2] => foo
)
This should be more memory efficient than the recursive approach. Despite the fact that we do a lot of array manipulation here, PHP has copy-on-write semantics so the actual zvals of the real data won't be duplicated in memory.
Try this:
function getLeafs($element) {
$leafs = array();
foreach ($element as $e) {
if (is_array($e)) {
$leafs = array_merge($leafs, getLeafs($e));
} else {
$leafs[] = $e;
}
}
return $leafs;
}
Edit Apparently you don’t want a recursive solution. So here’s an iterative solution that uses a stack:
function getLeafs($element) {
$stack = array($element);
$leafs = array();
while ($item = array_pop($stack)) {
while ($e = array_shift($item)) {
if (is_array($e)) {
array_push($stack, array($item));
array_push($stack, $e);
break;
} else {
$leafs[] = $e;
}
}
}
return $leafs;
}
Just got the same issue and used another method that was not mentioned. The accepted answer require the ArrayObject class to work properly. It can be done with the array primitive and the use keyword in the anonymous function (PHP >= 5.3):
<?php
$data = array(
array(1,2,3,4,5),
array(6,7,8,9,0),
);
$result = array();
array_walk_recursive($data, function($v) use (&$result) { # by reference
$result[] = $v;
});
var_dump($result);
There is no flatten function to get directly the leafs. You have to use recursion to check for each array if has more array children and only when you get to the bottom to move the element to a result flat array.