I'm having an issue with displaying object properties.
normally you would call them using :
$obj["name"]
but what if you did not know the properties e.g "name"
for an array , you can simply call $arr[0] , $arr[1] etc...
But if i have this object (print_r):
stdClass Object ( [id] => 1 [Name] => george [Number] => 437439742 [Email] => hds#gmail.com)
stdClass Object ( [id] => 2 [Name] => tom [Number] => 4343554643 [Email] => fdhk#gmail.com)
how can i use a foreach to display all the values e.g : 1 , george , 437...
-Without knowing the name of the properties -> NOT $o["id"];
foreach($object as $o)
{
echo $o[i]; // doesn't work on objects
}
I tried converting it to arrays , but it will be an array of the objects so i can;t get the inside info.
//$array = array ($object);
You have a couple of options. One is the get_object_vars() function, and another is to cast the object to an array.
foreach (get_object_vars($object) as $var => $val) {
// ...
}
or
foreach ((array) $object as $var => $val) {
// ...
}
You can use:
$array = get_object_vars($obj);
Related
I don't know what to do to get this done what would like to do. I tried multiple approaches, e.g. I used array_map, array_walk, nested foreach loops with get_object_vars and I worked with json_decode/encode and so on. I always come a little bit further but never reach my goal and I would like to get some guidance from you
Basically when you see the array below, how would you proceed when you want to change some value in the path array for multiple values in the array itself?
My questions:
1) Is it right that I must convert both nested objects to an array first or is this not nesessary to do this? I mean I always get some type conversion error which tells me that I either have everything as an object or array. Is this right?
2) If this mistery is solved, which php array function is the appropriate one to change values in an array(/object)? As I have written above, I tried so many and I don't see the trees in the woods anymore. Which one do you suggest to me to use in a foreach loop?
Array
(
[0] => stdClass Object
(
[doc] => stdClass Object
(
[path] => Array
(
[0] => Bob
[1] => pictures
[2] => food
)
)
)
[1] => stdClass Object
(
[doc] => stdClass Object
(
[path] => Array
(
[0] => Alice
[1] => pictures
[2] => vacations
[3] => rome
)
)
)
)
I would suggest that,
you create an array with keys as new path and value as old path (
path to be replaced).
Loop you path array and check if it is available in above defined array.
If available replace it with key of above defined array.
For example
// array defined as point 1
$change_path_array= array('pics'=>'pictures','meal'=>'food');
// $array is your array.
foreach ($array as $value) {
// loop you path array
for($i=0;$i<count($value->doc->path);$i++){
// check if the value is in defined array
if(in_array($value->doc->path[$i],$change_path_array)){
// get the key and replace it.
$value->doc->path[$i] = array_search($value->doc->path[$i], $change_path_array);
}
}
}
Out Put: picture is replaced with pics and food with meal
Array
(
[0] => stdClass Object
(
[doc] => stdClass Object
(
[path] => Array
(
[0] => Bob
[1] => pics
[2] => meal
)
)
)
[1] => stdClass Object
(
[doc] => stdClass Object
(
[path] => Array
(
[0] => Alice
[1] => pics
[2] => vacations
[3] => rome
)
)
)
)
You can modify the code to check casesensitive.
Example of changing all pictures to photos:
$doc1 = new \stdClass;
$doc1->doc = new \stdClass;
$doc1->doc->path = array('Bob', 'pictures', 'food');
$doc2 = new \stdClass;
$doc2->doc = new \stdClass;
$doc2->doc->path = array('Alice', 'pictures', 'vacations', 'rome');
$documents = array($doc1, $doc2);
/* change all 'pictures' to 'photos' */
foreach ($documents as &$doc) {
foreach ($doc->doc->path as &$element) {
if ($element == 'pictures') {
$element = 'photos';
}
unset($element);
}
unset($doc);
}
print_r($documents);
You can do it like this:
for($i = 0; $i < count($arr); $i++){
$path_array = $arr[$i]->doc->path;
// do your modifications for [i]th path element
// in your case replace all 'Bob's with 'Joe's
$path_array = array_map(function($paths){
if($paths == 'Bob') return 'Joe';
return $paths;
}, $paths_array);
$arr[$i]->doc->path = $path_array;
}
I have a database query which returns several records, however I would like to append more data to this object by typing the array as an object so that I can for example add more data to the output than the database contains.
I have done some research on this and found some functions such as array_merge but whenever I attempt to use this it gave me issues related to the array's depth and sometimes even created an entirely new array key instead of adding onto the currently existing ones.
This is the data from my database:
Array
(
[Cat] => Array
(
)
[Dog] => Array
(
)
[Rabbit] => Array
(
[0] => stdClass Object
(
[name] => fluffy
[owner] => foobar
)
[1] => stdClass Object
(
[name] => toby
[owner] => foobar
)
[2] => stdClass Object
(
[name] => josie
[owner] => Joseph
)
)
)
I'd like to make it so that every array key which exist have an extra field but other animals remain empty if they do not have any records.
Example:
Array
(
[Cat] => Array
(
[0] => stdClass Object
(
[name] => ralph
[owner] => Joseph
[extra] => some extra data
)
)
[Dog] => Array
(
)
[Rabbit] => Array
(
[0] => stdClass Object
(
[name] => fluffy
[owner] => foobar
[extra] => some extra data
)
[1] => stdClass Object
(
[name] => toby
[owner] => foobar
[extra] => some extra data
)
[2] => stdClass Object
(
[name] => josie
[owner] => Joseph
[extra] => some extra data
)
)
)
The reason I am attempting to merge the two is because I have several helper functions which generate pretty results and I'd like to utilize them rather than output the raw data from the database, the extra data is demonstration of how i'd like to merge onto the current array.
Thanks!
EDIT - Updated code:
function listPets(){
$foo = [];
foreach($pets as $p){
$getPets = $database->Findall("SELECT name, owner, info FROM pets...");
$foo[$p->name] = $getPets;
foreach($foo as $arr){
if(count($arr)){
foreach($arr as $v){
$v->extra = $this->message($getPets->info);
}
}
}
}
return $foo;
}
The solution is:
Loop through the array using foreach loop.
Check if the inner array is empty or not.
If the inner array is not empty then loop through it and append extra property to each of the objects.
So your code should be like this:
// Suppose $array is your original array
foreach($array as $arr){
if(count($arr)){ // check if the array is empty or not
foreach($arr as $v){
$v->extra = 'some extra value'; // append extra property to the object
}
}
}
// display $array
echo '<pre>';
print_r($array);
echo '</pre>';
Here's the demo:
Live Demo
Are you actually trying to merge two arrays or just append some extra information to the non-empty keys in the array of animals?
In the second case, depending on the information you want to add, there's two ways you could go:
Add it to the SELECT statement:
SELECT name, owner, 'extra stuff' as extra FROM ...
Do it like #rajdeep-paul said. Only you can skip the empty array check, if it's empty, foreach will not iterate through it anyway:
foreach ($dbData as $animals) {
foreach ($animals as $animal) {
$animal->extra = 'extra stuff';
}
}
The function below merges arrays & objects:
UPDATE
<?
function fuse_data()
{
$list = func_get_args();
$data = array_shift($list);
$type = gettype($data);
$data = ((array)$data);
foreach ($list as $indx => $item)
{
foreach ($item as $name => $valu)
{
if (!isset($data[$name]) || empty($data[$name]))
{
$data[$name] = $valu;
}
}
}
return (($type == 'object') ? ((object)$data) : $data);
}
?>
Use it like this:
$data = fuse_data($result, $node2, $list3, $foo, $bar);
Edit as you like, it's just a proof of concept.
You can do something like ...
foreach($pets as &$pet) { // passing by reference to manipulate the original array.
if(!empty($pet) && is_array($pet)){ // Checking if the element is an array and not empty
foreach($pet as &$feature){ // Again passing by reference the 2nd dimension
if(is_object($feature)){ // Checking if the element is object to prevent the "Property of non-object" error.
$feature->extra = 'Some value'; // If all is well, we asign the new property to the object.
}
}
}
}
Now even though I think there are better ways to write(optimize) a query than firing it inside a loop!!! but just for the sake of your question, your code should be like..
function listPets(){
$foo = [];
foreach($pets as $p){
$getPets = $database->Findall("SELECT name, owner, info FROM pets...");
$foo[$p->name] = $getPets;
foreach($foo as $arr){
if(is_array($arr) && count($arr)){
foreach($arr as $v){
if(!empty($v) && is_object($v)){
$v->extra = $this->message($getPets->info);
}
}
}
}
}
return $foo;
}
I have a class like so:
stdClass Object
(
[id] => 1
[items] => stdClass Object
(
[0] => 123
[1] => 234
[2] => 345
[3] => 456
)
)
)
Let's call the above object $foo.
Let's say $v = 234. Given $foo and $v, how can I return the "key" 1?
If $foo->items was an array I would simply do $key = array_search($v,$foo->items);. But this doesn't work in an object.
How can I find the key for $v without looping through the object in some foreach?
Use get_object_vars and search through the array returned.
Reference: http://php.net/manual/en/function.get-object-vars.php
Here's an example of how to search through the array returned for a key:
<?php
$foo = NULL;
$foo->id = 1;
$foo->items = array(123, 234, 345, 456);
$foo_array = get_object_vars($foo);
print_r($foo_array);
foreach ($foo_array as $key => $value) {
if ($value == 1) {
echo $key;
}
}
?>
Output:
Array
(
[id] => 1
[items] => Array
(
[0] => 123
[1] => 234
[2] => 345
[3] => 456
)
)
id
CodePad: http://codepad.org/in4w94nG
As you have shown in your example, you're dealing with stdClass object(s). Those are quite similar to arrays and with PHP you can easily convert between those two with something called casting:
$object = $foo->items;
$key = array_search($v, (array)$object);
^^^^^^^--- cast to array
As this little example shows (I just used the $object variable to make the cast more visible, you normally can write it as one-liner), the cast from object to array does allow you to use the known function (array_search) on the object.
Because arrays and stdClass objects in PHP are so similar, this works in both directions:
$array = ['property' => 'value'];
$object = (object)$array;
echo $object->property; # value
This also works with other types in PHP, so probably apart from your concrete problem, something worth to read about: Type JugglingÂDocs, but take care, that in PHP this has many special rules. But between array and objects, it's pretty straight forward.
$key = array_search($v, get_object_vars($foo->items));
edit: try this
So if having a multidimensional array like:
Got it from here (as a demo): PHP. Loop through an array and get items with attributes in common
$data
Array
(
[0] => stdClass Object
(
[term_id] => 3
[name] => Comercial
)
[1] => stdClass Object
(
[term_id] => 4
[name] => Escolar
)
[2] => stdClass Object
(
[term_id] => 5
[name] => Kinder
)
[3] => stdClass Object
(
[term_id] => 6
[name] => Primaria
)
[4] => stdClass Object
(
[term_id] => 7
[name] => Secundaria
)
[5] => stdClass Object
(
[term_id] => 1
[name] => Uncategorized
)
)
Having 0,1,2,3,4,5 stdClass Objects, how can I create individual arrays for each std Object dynamically.
By that I mean that the function should be able to create $varX array, where X is the array number of the stdObject, automatically...
$var0 = $data[0];
$var1 = $data[1];
and so on, determined by $data first level count of arrays.
Edit:
I got carried away and forgot to mention the most important question:
Having $var0, $var1... is very important because for a later use of all or each one individually.
So
Needs to create X variables according to the count of first level of the multidimensional array
each $varX needs to be accessible in common with the rest of $varX or individually.
$count = count($data); //6
foreach ($data as $key => $value)
{
$var.$key = $value;
}
Ok, that function works partially because from there I don't know how to make it automatically add $val1,$val2... to (ex:) array_intersect($val1,$val2,$val3...
The easiest way would be to use extract.
extract($data, EXTR_PREFIX_ALL, 'var');
With that said, it will add an underscore (_) after the prefix (e.g. var_0).
Update:
Regarding your edit, you could simply call array_intersect using call_user_func_array. There's no need for variables.
call_user_func_array('array_intersect', $data);
foreach ($data as $key => $obj)
{
$key = 'var'.$key;
$$key = $obj;
}
You can just cast each object to an array.
foreach ($data AS $key => $datum)
{
$data[$key] = (array) $datum;
}
For your update:
foreach ($data AS $key => $datum)
{
$newkey = 'var' . $key; // we want the variable to be called "var" plus the number
$$newkey = (array) $datum; // Make it an array
$data[$key] = $$newkey; // And update the $data array to contain the array
}
You now have $var0, $var1, etc and can also access them as a collection in $data, and they're in both as an array.
This is what I want but cant figure out how to.
$a is this array
PHP Code:
Array
(
[0] => stdClass Object
(
[id] => i1
[cat] => Test1
)
[1] => stdClass Object
(
[id] => i2
[cat] => Test2
)
[2] => stdClass Object
(
[id] => i3
[cat] => Test3
)
[3] => stdClass Object
(
[id] => i4
[cat] => Test4
)
}
This is the array and it has those std classes associated with it. What I am trying to do is to combine all the "cat" names into one array variable.
I want to make $categories an array with all these "cat" as the array values.
How can I do that ?
array_map($a, function(stdClass $o) { return $o->cat; });
A simple way is just to loop over the array, grabbing the values that you want. There are other, fancier ways of doing the same but I like to keep it simple.
$categories = array();
foreach ($a as $obj) {
$categories[] = $obj->cat;
}
Of course, if not all of the array items are that object then it might be worthwhile to check that the cat property exists (and that $obj is a stdClass!).
Simply loop through and create a new array...
<?php
$newArray = array();
foreach($a as $cat) {
$newArray[$cat->id] = $cat->cat;
}
var_dump($newArray);