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.
Related
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.
I'm developping a website, where if a user changes some data, it should be stored on the background, to see who did last change and what etc... . I have 1 object called Event, but the data onscreen is devided into 2 tabs (Client and Event). After the submit, I get all the fields and put the data in the object. I have this self made function to compare the values in the new boject with the values of the old object:
function createArrayReturnDiff($obj1, $obj2) {
$helpArray1 = (array) $obj1; //convert object to array
$helpArray2 = (array) $obj2; //convert object to array
$help = array_diff_assoc($helpArray2, $helpArray1); //Computes the difference of arrays with additional index check
return $help;
}
Now this works all fine, I get an array returned with names of the field and the new value.
But here comes the tricky part. After the return of this array, I loop trough it I want to check which tab the value was on in order to give beter user feedback later. So if the value is on Cleint or Event tab. Now I made 2 arrays where I describe all the fields in each tab.
$tabKlant = array('Evenementfirmanaam', 'Evenementaanspreking', 'Evenementcontactpersoon', 'Evenementcontactpersoonstraat', 'Evenementcontactpersoongemeente', 'Evenementcontactpersoonland', 'Evenementcontactpersoonmail', 'Evenementcontactpersoontel', 'Evenementgeldigheidsdatum', 'Evenementfacturatiegegevens', 'Evenementfactuur_mededeling', 'Evenementbestelbon', 'Evenementreferentie');
$tabEvenement = array('Evenementstartdatum', 'Evenementeinddatum', 'Evenementnaam', 'Evenementfeestlocatie', 'Evenementcontactfeestlocatie', 'Evenementaantal', 'Evenementact_speeches_opm', 'Evenementdj', 'Evenementinleiding');
Now my code to check:
foreach ($help as $key => $value) {
if (in_array($key, $tabEvent)) {
$tab = "Event";
} else if (in_array($key, $tabClient)) {
$tab = "Client";
} else {
$tab = "";
}
}
Now what I tried to change was Evenementfirmanaam, so the $help array contains values with key = Evenementfirmanaam and value = 'xxxx'. Everything looks like it is supposed to work. But for some reason, it can't find the value in the in_array of my foreach.
After I tried to write away data to the database. I used a mysqli_real_escape_string on the $key of my help array (firmanaam in this case) and I found out it is creating the string like: '\0Evenement\0firmanaam' . I have no idea why the \0 are added, but I have a feeling this is the reason why the in_array function won't compare my values properly. Does anyone have an idea what the problem might be?
The problem is that the firmanaam property of your Evenement class (which $obj1 and $obj2 look like to be instances of) is private, which results in the cast to array creating special keys:
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.
This can result in some unexpected behaviour.
In essence, you are being punished for violating the logical design of your class: if $firmanaam is private the outside world should not have any access to its value. The cast to array does allow you to get the value but you really should not do this.
Since you are using Evenement to encapsulate and hide data members, do it all the way. If you want access to those members, provide for and use a getter. If you want to compare two instances with specific semantics, add a comparison method to the class.
When I compared two different objects, it returns firstly true, and than after print_r (on objects) returned false.
From PHP manual:
Two object instances are equal if they have the same attributes and values, and are instances of the same class.
But here, in example, I set different values. Why the result is different between PHP 5.4.0 - 5.5.7?
abstract class first
{
protected $someArray = array();
}
class second extends first
{
protected $someArray = array();
protected $someValue = null;
public function __construct($someValue)
{
$this->someValue = $someValue;
}
}
$objFirst = new second('123');
$objSecond = new second('321');
var_dump ($objFirst == $objSecond);
print_r($objFirst);
var_dump ($objFirst == $objSecond);
Result is:
bool(true)
second Object ( [someArray:protected] =>
Array ( ) [someValue:protected] => 123 )
bool(false)
But what I expected was:
bool(false)
second Object ( [someArray:protected] =>
Array ( ) [someValue:protected] => 123 )
bool(false)
This was a bug in PHP. It's fixed now, see the commit. In short:
If you extend a class and redefine the same property the properties_table of the object ends up having a NULL value.
The comparison code incorrectly aborted comparison when two objects had a NULL value in the properties_table at the same index - reporting the objects as equal. That doesn't make sense of course, because it discards all differences in the following properties. This is fixed now.
The reason why print_r changes the result, is that by fetching the properties of the object (get_properties) the properties hashtable is rebuilt (rebuild_properties_table) which uses entirely different (and correct) comparison code.
For context, properties_table and properties are two different ways PHP uses to represent properties - the former being way more efficient and used for declared properties and the latter used for dynamic properties. The print_r call effectively makes the object properties dynamic.
Well, ok, Identified as bug in php https://bugs.php.net/bug.php?id=66286.
Also here: Unexpected result when comparing PHP objects
I know that some array functions, such as array_rand, work for objects as long as you put (array) in front of the object. In this case I am trying to get the ID of the
$this->id = end($this->log->r);
this returns all of the elements in the last element. I just want to know what the key of that element is. This is a JSON_decoded object.
end() sets the pointer to the last property defined in the object and returns its value.
When the pointer is moved, you can call the key() function to get the property name
<?php
$object = new stdClass();
$object->first_property = 'first value';
$object->second_property = 'second value';
$object->third_property = 'third value';
$object->last_property = 'last value';
// move pointer to end
end($object);
// get the key
$key = key($object);
var_dump($key);
?>
Outputs
string 'last_property' (length=13)
This functionality is identical for arrays How to get last key in an array
You can cast array before apllying end() method on an object :
# $menu_items is an object returned by wp_get_nav_menu_items() wordpress method
$menu_items = wp_get_nav_menu_items('nav_menu');
$last_item = (array) end($menu_items);
print_r($last_item['title']);
<?
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] );