Iterating over multidimensional PHP Object and changin values by reference - php

I am trying to iterate over a php object and changing each string value by reference, but something is just not working. In some arrays the strings will not be changed. Anyone has an idea why? Or has a suggestion on how to solve the task?
Here is my code:
recursive_object_string_changer($object);
function recursive_object_string_changer($object)
{
if($object == null) {
return;
}
foreach ($object as &$attribute) {
if (is_string($attribute)) {
$attribute = $attribute."!";
} else if (is_array($attribute)) {
recursive_object_string_changer($attribute);
} else if (is_object($attribute)) {
recursive_object_string_changer($attribute);
}
}
unset($attribute);
}
Thank you very much!

I think you want to make the function's signature also accept the initial object as a reference so that the recursion works on subsequent calls.
recursive_object_string_changer($object);
function recursive_object_string_changer(&$object)
{
if ($object === null) {
return;
}
foreach ($object as &$attribute) {
if (is_string($attribute)) {
$attribute .= "!";
} elseif (is_array($attribute)) {
recursive_object_string_changer($attribute);
} elseif (is_object($attribute)) {
recursive_object_string_changer($attribute);
}
}
unset($attribute);
}
I used this for a sample:
$object = new stdClass();
$object->string = 'Test';
$object->array = [
'a',
'b',
'c',
];
$subObject = new stdClass();
$subObject->string = 'Another String';
$object->object = $subObject;
Which produces:
object(stdClass)#1 (3) {
["string"]=>
string(5) "Test!"
["array"]=>
array(3) {
[0]=>
string(2) "a!"
[1]=>
string(2) "b!"
[2]=>
string(2) "c!"
}
["object"]=>
object(stdClass)#2 (1) {
["string"]=>
string(15) "Another String!"
}
}
You might always want to add a guard before the for loop to make sure that $object is an array or an object in the first place.

Related

How to simply return the result of a promise?

I am using this telegram api to make an api call. It works, but i cant get this result returned. This is what I have:
$loop = \React\EventLoop\Factory::create();
$handler = new HttpClientRequestHandler($loop);
$tgLog = new TgLog($token, $handler);
$webHookInfo = new GetWebhookInfo();
$promise = $tgLog->performApiRequest($webHookInfo);
$promiseResult = $promise->then(
function (WebhookInfo $info)
{
print 'Y';
return $info;
},
function (\Exception $e) {
print 'X';
return $e->getMessage();
}
);
$loop->run();
It prints the "Y" and I can even var_dump $info and see the result I want. But outside of that function, I cant access it. This is what I see if I var_dump($promiseResult):
object(React\Promise\Promise)#1582 (6) {
["canceller":"React\Promise\Promise":private]=>
NULL
["result":"React\Promise\Promise":private]=>
object(React\Promise\FulfilledPromise)#1597 (1) {
["value":"React\Promise\FulfilledPromise":private]=>
object(unreal4u\TelegramAPI\Telegram\Types\WebhookInfo)#1450 (8) {
["url"]=> string(84) "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
["has_custom_certificate"]=> bool(false)
["pending_update_count"]=> int(0)
["last_error_date"]=> int(1595489318)
["last_error_message"]=> string(20) "Read timeout expired"
["max_connections"]=> int(100)
["allowed_updates"]=> array(0) {
}
["logger":protected]=> object(unreal4u\Dummy\Logger)#1047 (0) {
}
}
}
["handlers":"React\Promise\Promise":private]=> array(0) {
}
["progressHandlers":"React\Promise\Promise":private]=> array(0) {
}
["requiredCancelRequests":"React\Promise\Promise":private]=> int(0)
["cancelRequests":"React\Promise\Promise":private]=> int(0)
}
I am actually after that url that I blanked out with X's. But there is no method on this object to get that value.
What am I missing?

Converting multidimensional object to array

I have a following object:
object(Intro\IntroBundle\Entity\User)#333 (6) {
["id":"Intro\IntroBundle\Entity\User":private]=>
int(3)
["username":"Intro\IntroBundle\Entity\User":private]=>
string(3) "aaa"
["email":"Intro\IntroBundle\Entity\User":private]=>
string(9) "aa#aa.com"
["password":"Intro\IntroBundle\Entity\User":private]=>
string(4) "a1a1"
["age":"Intro\IntroBundle\Entity\User":private]=>
int(10)
["dateCreated":"Intro\IntroBundle\Entity\User":private]=>
object(DateTime)#330 (3) {
["date"]=>
string(26) "2011-01-01 01:01:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
}
I used methods:
array($entity);
json_decode(json_encode($entity), true);
get_object_vars ($entity);
and with a personal method
private function objToArray($obj){
$arr = array();
if(!is_object($obj) && !is_array($obj)){
$arr = $obj;
die("invalid data");
}
foreach ($obj as $key => $value)
{
if (!empty($value))
{
$arr[$key] = array();
objToArray($value, $arr[$key]);
}
else
{
$arr[$key] = $value;
}
}
return $arr;
}
All those methods return an empty array. Please tell me why? I mention that my object input ($entity) is not empty.
And also please don't give me dislike if you do not know the answer.
Your object's properties are private. If you var_dump() an object as you did it prints also private properties.
Have a look at this article http://php.net/manual/en/language.oop5.iterations.php. You can iterate object as you do but it iterates only public properties.
First of all, we can't see the scope. All your code is private (object properties and the method). Show the scope and we can help you better.
The problem seems to be here:
if (!empty($value))
{
$arr[$key] = array();
objToArray($value, $arr[$key]);
}
You are passing a second argument that doesn't defined in the method
private function objToArray($obj){...}
So you are passing a value to objToArray(), that value is a string I guess, and when it reach this line:
$arr = array();
if(!is_object($obj) && !is_array($obj)){
$arr = $obj;
die("invalid data");
}
Then it will display "invalid data", and empty your array.

Can't retrieve associative array index in php

I have an array that looks like the following:
array(3) { [0]=> array(1)
{
["habitacionales"]=> array(1)
{ ["Azcapotzalco"]=> string(1) "3" } }
[1]=> array(1) { ["comerciales"]=> array(0) { } }
[2]=> array(1) { ["industriales"]=> array(0) { } }
}
And I need to check if the array belongs to the type "habitacionales", or "comerciales", etc. But no matter what I do, I keep getting the notice "Undefined index: habitacionales". Could someone point out how to access that index?
I am using cakephp, and I am setting the variables in the controller like this:
$zonasHab = $this->PropiedadesHabitacionale->BasicosPropiedadesHabitacionale->find('list', array('fields'=>array('Zona', 'propiedad_habitacional_id')));
then I do:
$this->set('Zonas', array_unique($linksZonas, SORT_REGULAR));
And finally in the view I do:
foreach ($Zonas as $zona) {
foreach($zona as $zone) {
foreach(array_flip($zone) as $link) {
echo '<li class="dropdownheader">'.$link;
}
var_dump($zone['habitacionales']);
}/*
if($zona['habitacionales']!=null)
foreach(array_flip($zone) as $vinculo) {
echo '<li>'.$this->Html- >link($vinculo, array('controller'=>'propiedadeshabitacionales', 'action'=>'ver', $vinculo)).'</li>';
}
*/
echo '</li>';
}
Just to point out, the wierd thing is that if I do var_dump($zona['habitacionales']); inside the outer foreach, I get the correct value: array(1) { ["Azcapotzalco"]=> string(1) "3" } but I still get the notice appearing telling me it's an undefined index, and I can't use that same syntax ($zona['habitacionales'] for a condition or anything else.
Assuming $Zonas is that array above, try:
foreach($zona as $zone) {
foreach(array_flip($zone) as $link) {
echo '<li class="dropdownheader">'.$link;
}
var_dump($zone);
habitacionales is the key, if you want to access that then use:
foreach($zona as $key => $zone) {
And $key should be set to habitacionales.

How to add (any type )value to an array(by specified index) in php language

As title, I did it like below:
$array=array(0,1,2,3);
$result=array();
function makeArray($array,$result,$value){
$str='$result';
for ($i=0;$i<count($array);$i++){
$str.='['.$i.']';
}
$str.='="'.$value.'";';
eval($str);
return $result;
}
It can realize result when param $result is an empty array,but It report an error when $result is an array.
Error like :
Cannot use a scalar value as an array.
Anyways can realize it?
Thanks first!
Use pass by reference, not eval:
function makeArray($indexes, &$result, $value) {
$here =& $result;
foreach ($indexes as $i) {
if (!(isset($here[$i]) && is_array($here[$i]))) {
$here[$i] = array();
}
$here =& $here[$i];
}
$here = $value;
}
$array=array(0,1,2,3);
$result=array();
makeArray($array, $result, 3);
var_dump($result);
Output:
array(1) {
[0]=>
array(1) {
[1]=>
array(1) {
[2]=>
array(1) {
[3]=>
int(3)
}
}
}
}
Putting & before a function parameter means it will be passed by reference, so modifications to the variable inside the function will affect the original variable that was passed. And using =& in an assignment assigns a reference, so the target variable is an alias for the source.

Convert multidimensional objects to array [duplicate]

This question already has answers here:
Convert a PHP object to an associative array
(33 answers)
Closed 6 months ago.
I'm using amazon product advertising api. Values are returned as a multidimensional objects.
It looks like this:
object(AmazonProduct_Result)#222 (5) {
["_code":protected]=>
int(200)
["_data":protected]=>
string(16538)
array(2) {
["IsValid"]=>
string(4) "True"
["Items"]=>
array(1) {
[0]=>
object(AmazonProduct_Item)#19 (1) {
["_values":protected]=>
array(11) {
["ASIN"]=>
string(10) "B005HNF01O"
["ParentASIN"]=>
string(10) "B008RKEIZ8"
["DetailPageURL"]=>
string(120) "http://www.amazon.com/Case-Logic-TBC-302-FFP-Compact/dp/B005HNF01O?SubscriptionId=AKIAJNFRQCIJLTY6LDTA&tag=*********-20"
["ItemLinks"]=>
array(7) {
[0]=>
object(AmazonProduct_ItemLink)#18 (1) {
["_values":protected]=>
array(2) {
["Description"]=>
string(17) "Technical Details"
["URL"]=>
string(217) "http://www.amazon.com/Case-Logic-TBC-302-FFP-Compact/dp/tech-data/B005HNF01O%3FSubscriptionId%3DAKIAJNFRQCIJLTY6LDTA%26tag%*******-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB005HNF01O"
}
}
[1]=>
object(AmazonProduct_ItemLink)#17 (1) {
["_values":protected]=>
array(2) {
I mean it also has array inside objects. I would like to convert all of them into a multidimensional array.
I know this is old but you could try the following piece of code:
$array = json_decode(json_encode($object), true);
where $object is the response of the API.
You can use recursive function like below:
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();
objToArray($value, $arr[$key]);
}
else {$arr[$key] = $value;}
}
return $arr;
}
function convertObjectToArray($data) {
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
return array_map(__FUNCTION__, $data);
}
return $data;
}
Credit to Kevin Op den Kamp.
I wrote a function that does the job, and also converts all json strings to arrays too. This works pretty fine for me.
function is_json($string) {
// php 5.3 or newer needed;
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
function objectToArray($objectOrArray) {
// if is_json -> decode :
if (is_string($objectOrArray) && is_json($objectOrArray)) $objectOrArray = json_decode($objectOrArray);
// if object -> convert to array :
if (is_object($objectOrArray)) $objectOrArray = (array) $objectOrArray;
// if not array -> just return it (probably string or number) :
if (!is_array($objectOrArray)) return $objectOrArray;
// if empty array -> return [] :
if (count($objectOrArray) == 0) return [];
// repeat tasks for each item :
$output = [];
foreach ($objectOrArray as $key => $o_a) {
$output[$key] = objectToArray($o_a);
}
return $output;
}
This is an old question, but I recently ran into this and came up with my own solution.
array_walk_recursive($array, function(&$item){
if(is_object($item)) $item = (array)$item;
});
Now if $array is an object itself you can just cast it to an array before putting it in array_walk_recursive:
$array = (array)$object;
array_walk_recursive($array, function(&$item){
if(is_object($item)) $item = (array)$item;
});
And the mini-example:
array_walk_recursive($array,function(&$item){if(is_object($item))$item=(array)$item;});
In my case I had an array of stdClass objects from a 3rd party source that had a field/property whose value I needed to use as a reference to find its containing stdClass so I could access other data in that element. Basically comparing nested keys in 2 data sets.
I have to do this many times, so I didn't want to foreach over it for each item I need to find. The solution to that issue is usually array_column, but that doesn't work on objects. So I did the above first.
Just in case you came here as I did and didn't find the right answer for your situation, this modified version of one of the previous answers is what ended up working for me:
protected function objToArray($obj)
{
// Not an object or array
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
// Parse array
foreach ($obj as $key => $value) {
$arr[$key] = $this->objToArray($value);
}
// Return parsed array
return $arr;
}
The original value is a JSON string. The method call looks like this:
$array = $this->objToArray(json_decode($json, true));

Categories