Retrieving PHP property name as string - php

I have some JSON, if I var_dump the output looks like:
var_dump( $oJSON->{$oQ->sQuestionName} );
object(stdClass)[14]
public 'Lease' => boolean true
I would like to retrieve 'Lease' as a string.
I've tried casting it:
(string)$oJSON->{$oQ->sQuestionName}
but it returns an E_RECOVERABLE:
E_RECOVERABLE_ERROR Error: Object of class stdClass could not be converted to string
The following works, however I feel there must be a better way?
array_shift(array_values(array_keys(get_object_vars($oJSON->{$oQ->sQuestionName}))));
N.B. I can't use to use the following due to compatability issues
array_keys(get_object_vars($oJSON->{$oQ->sQuestionName}))[0]

Use ReflectionClass::getProperties() to get a list of the object's properties.
$reflect = new ReflectionClass($foo);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);

You can convert your desired object to an array first
$array = (array) $oJSON->{$oQ->sQuestionName};
Then you can take its first element's key
echo key($array); // Should say Lease
Fiddle

You can use json_decode with second parameter true
For example:
$str = '{"0":{"id":"123","name":"Title"}}';
var_dump(json_decode($str,true));
So, you will have an array with string objects.

Related

Why stdClass is coming instead of our custom object name?

Here My class name is User, When I print my class properties I'm getting my objective name properly. After that, I encoded the data with json_encode(). and then I decoding with json_decode(). I'm getting stdClass objective why?
<?php
class User
{
public $name;
public $age;
public $salary;
}
$user = new User();
$user->name = 'Siddhu';
$user->age = 24;
$user->salary = 7000.80;
print_r($user);
//Output: User Object ( [name] => Siddhu [age] => 24 [salary] => 7000.8 )
print_r(json_encode($user));
//Output: {"name":"Siddhu","age":24,"salary":7000.8}
$d = json_encode($user);
$s = json_decode($d);
print_r($s);
//Output: stdClass Object ( [name] => Siddhu [age] => 24 [salary] => 7000.8 )
If you noticed stdClass is coming, How can I change to user
There is no direct way you can get data in class object either you need to used custom method to decode else you can use serialize() && unserialize() function to get data in the class object when you decode;
$serialized_user_object = serialize($user);
$deserialized_user_object = unserialize($serialized_user_object);
In json_decode you can pass true in second argument if you want data as array.
like this.
var_dump(json_decode($json, true));
to know more about json_decode see here.
The reason this happens can be demonstrated quite easily...
class foo{
public $bar = 'bar';
}
$json = json_encode(new foo);
echo $json."\n\n";
print_r(json_decode($json));
Output
{"bar":"bar"}
stdClass Object
(
[bar] => bar
)
Sandbox
As you can see the output {"bar":"bar"} contains no information about what if any class this was, it could have been ['bar'=>'bar'] and the JSON would be the same... Then when decoding it, you don't have json_decode set to return as an array (second argument set to true), which is fine as that's not really what you want, but when it's set that way you get stdClass objects instead of an associative array for items with non-numeric keys. In short there is no way to recover the class "foo" from the json {"bar":"bar"} as that information does't exist (you can make it exist, but that's another tale for another day).
Using serialize we get something very different.
class foo{
public $bar = 'bar';
}
$json = serialize(new foo);
echo $json."\n\n";
print_r(unserialize($json));
Output
O:3:"foo":1:{s:3:"bar";s:3:"bar";}
foo Object
(
[bar] => bar
)
Sandbox
This O:3:foo means an Object with a class name 3 in length named "foo". So it preserves that information for PHP to use when "decoding" the data.
The whole thing reads like this:
Object (3) "foo" with 1 property named (s)tring (3) "bar" with a value of (s)tring (3) "bar", or something like that.
Make sense.
AS a note PHP's serialize is less portable then JSON, as it only works in PHP, It's also much harder to manually edit then JSON, but if you really want to encode a class than that is the easiest way to do it. That said you can also "repopulate" the class from JSON data, but that can also be hard to maintain.

PHP doesn't find array elements

A library I use uses an array. Applying print_r to that array prints this:
Array
(
[*queueId] => 1
[*handle] => 9b875867b36d568483fb35fdb8b0bbf6
[*body] => First string in the TestQueue
[*md5] => c23ba714199666efbc1dcd5659bb0a0a
[*timeout] => 1408003330.6534
[*id] => 2
[*creationdate] => 2014-08-13 16:03:37
)
The library uses a magic getter on that array
public function __get($key)
{
if (!array_key_exists($key, $this->_data)) {
throw new Exception\InvalidArgumentException("Specified field \"$key\" is not in the message");
}
return $this->_data[$key];
}
When I try to access
$myObject->body
I run into the exception. In fact, the debugger shows that array_key_exists will return false while the _data array is available as printed above
The asterisk indicates that this array is a representation of an object, probably the original object property is protected.
http://php.net/manual/en/language.types.array.php#language.types.array.casting
As I explained in the comments, the array keys actually start with an asterisk. Since you can't call them using the regular syntax of $obj->*body (it'll cause a syntax error), you can use the following:
$myObject->{'*body'}
This should solve your problem.
Assuming that $myObject is the array you are talking from:
You can't access arrays with ->, use $myObject['*body'] instead. (And you should as well change the name to $myArray, for example)
As #MarkBaker stated in the comment of my question, the problem was that I was serializing an object with private properties to the array. The asterisk were marks that these properties were private.

PHP JSON get the name of an object

<?
stdClass Object
(
[image_header] => Array
(
[0] => stdClass Object
(
[img] => /headers/header.jpg
)
)
)
?>
Object name image_header is variable, so it can be any string. Can I access this string without knowing what it is?
#Jon his answer was satisfying for me.
For others who want to use variable objectnames this way:
To acces this object with the variablename I had to use curly brackets:
$key = key(get_object_vars($_json));
$_json->{$key}[0]->img;
You can do it conveniently with get_object_vars:
$propertyName = key(get_object_vars($object));
If you don't know what the name of the property is, you can use PHP's Reflection classes, or more simply use get_object_vars().
get_object_vars() is probably what you're looking for here - it "Returns an associative array of defined object accessible non-static properties for the specified object in scope. If a property has not been assigned a value, it will be returned with a NULL value." So, you get the property names and their values returned in an associative array.
Alternatively, you could use some of PHP's reflection magic, although it might be a bit overkill here, depending on your end goal. The reflection classes are very powerful, and may be worth using if you have more complex requirements for what you're trying to achieve. As an example:
// let's say $obj is the object you provided in your question
// Instantiate the reflection object
$reflector = new ReflectionClass($obj);
// Get properties of $obj, returned as an array of ReflectionProperty objects
$properties = $reflector->getProperties();
foreach ( $properties as $property ) {
echo $property->getName(); // In your example, this would echo 'image_header'
}
There are a couple of possibilities. If you're using json_decode() you can pass true in as the second parameter to parse the data as an associative array.
$data = json_decode($myJson, true);
print_r( $data['image_header'] );
You can also access an object property from a variable like this.
$myProperty = 'image_header';
print_r( $data->$myProperty );
If by "you don't know what it is" you mean you don't know the key at all you can use my first example and use array_values() to get the values by index.
$values = array_values($data);
// image_header
print_r( $values[0] );

PHP Undefined index of array. Why?

This is... I don't even know what this is happening.
// var_dump of items before
object(stdClass)[84]
public '75' => object(stdClass)[87]
$items = (array) $items; // Casting unserialized stdClass to array
var_dump($items);
//Result of var dump:
array
'75' =>
object(stdClass)[87]
//Now lets get this item:
var_dump($items[75]); // Error
var_dump($items['75']); // Error
What the?
Thanks.
I think, you are using a debug extension, so the var_dump() output is different then standart library, properties can not be numeric but $obj->{'75'} is okay.
If can you reach to the sub object by $items->{'75'} yes you have a numeric property.
otherwise you can try print_r($items); and see the original output, or check the array after get_object_vars()
<?php
$items = new stdClass();
$items->{'75'} = new stdClass();
$items->{'75'}->{'85'} = new stdClass();
$items = (array) $items; // Casting unserialized stdClass to array
$items_array = get_object_vars($items); // getting object vars as an array.
var_dump($items["75"]); // Error
var_dump($items['75']); // Error
var_dump($items_array['75']); // Works
PHP issue : #45959
Read the casting blockquote: http://www.php.net/manual/en/language.types.array.php#language.types.array.casting
Casting to an array doesn't work like that.
See here: get_object_vars() vs. cast to array
and here: http://www.php.net/manual/en/language.types.array.php#language.types.array.casting
Blockquote
"If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side.

Dynamically discover/process PHP object

Is it possible to dynamically discover the properties of a PHP object? I have an object I want to strip and return it as a fully filled stdClass object, therefore I need to get rid of some sublevel - internal - objecttypes used in the input.
My guess is I need it to be recursive, since properties of objects in the source-object can contain objects, and so on.
Any suggestions, I'm kinda stuck? I've tried fiddling with the reflection-class, get_object_vars and casting the object to an array. All without any success to be honest..
tested and this seems to work:
<?php
class myobj {private $privatevar = 'private'; public $hello = 'hellooo';}
$obj = (object)array('one' => 1, 'two' => (object)array('sub' => (object)(array('three' => 3, 'obj' => new myobj))));
var_dump($obj);
echo "\n", json_encode($obj), "\n";
$recursive_public_vars = json_decode(json_encode($obj));
var_dump($recursive_public_vars);
You can walk through an object's (public) properties using foreach:
foreach ($object as $property => $value)
... // do stuff
if you encounter another object in there (if (is_object($value))), you would have to repeat the same thing. Ideally, this would happen in a recursive function.

Categories