Array to Object and Object to Array in PHP - interesting behaviour
The array key contains a marker that this should be a private property of the class test.
Compare your scripts output with the following:
$array = array(
"xpublic" => "x1",
# this will become a private member:
"\x00test\x00xprivate" => "x2",
# this will become a protected member:
"\x00*\x00xprotected" => "x3"
);
var_dump($array);
$obj = (object) $array;
var_dump($obj);
When serialized, the same string is used to describe the private members.
Output:
array(3) {
["xpublic"]=>
string(2) "x1"
["testxprivate"]=>
string(2) "x2"
["*xprotected"]=>
string(2) "x3"
}
object(stdClass)#1 (3) {
["xpublic"]=>
string(2) "x1"
["xprivate":"test":private]=>
string(2) "x2"
["xprotected":protected]=>
string(2) "x3"
}
In the output of var_dump()
, the null bytes are not visible.
(Update: Added protected class member)
Cast object to array - strange behaviour
When casting an object to an array, certain properties (private, protected and parent properties) are assigned to the array, with keys that look like:
*protected
ClassNamePrivate
ParentNameProperty
But they really look like this:
"\0*\0protected"
"\0ClassName\0Private"
"\0ParentName\0Property"
That's what's causing your problems here.
Replace:
echo $new['EPPContactemail'];
with
echo $new["\0EPPContact\0email"];
And take it from there.
Note that you'll have to use double quotes as string delemiters, because '\0' !== "\0"
, just as '\n' !== "\n"
This behaviour is documented on php.net, though it's rather well hidden
(array) type cast strange behaviour object to array conversion
A few findings I have here:
Quoted from:
- A numeric string as array key in PHP
- http://www.php.net/manual/en/language.types.array.php
They state that:
Strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8. On the other hand "08" will not be cast, as it isn't a valid decimal integer.
What's interesting is (slightly modifying your test script):
<?php
$json = '{"1455260079":"Tracking : #34567808765098767 USPS","1455260723":"Delivered","1455261541":"Received Back"}';
$json_obj = json_decode($json);
$json_array = (array) $json_obj;
var_dump($json_array);
print_r($json_array);
$newerArray = array();
echo "json_array contents: \n";
foreach($json_array as $k => $v){
echo "k: $k " . gettype($k) . ", v: $v " . gettype($v) . "\n";
$newerArray[$k] = $v;
}
echo "\n";
echo "newerArray contents: \n";
foreach($newerArray as $k => $v){
echo "k: $k " . gettype($k) . ", v: $v " . gettype($v) . "\n";
}
echo $json_array["1455260079"]."\n";
echo $newerArray["1455260079"]."\n";
The output is:
array(3) {
["1455260079"]=>
string(34) "Tracking : #34567808765098767 USPS"
["1455260723"]=>
string(9) "Delivered"
["1455261541"]=>
string(13) "Received Back"
}
Array
(
[1455260079] => Tracking : #34567808765098767 USPS
[1455260723] => Delivered
[1455261541] => Received Back
)
json_array contents:
k: 1455260079 string, v: Tracking : #34567808765098767 USPS string
k: 1455260723 string, v: Delivered string
k: 1455261541 string, v: Received Back string
newerArray contents:
k: 1455260079 integer, v: Tracking : #34567808765098767 USPS string
k: 1455260723 integer, v: Delivered string
k: 1455261541 integer, v: Received Back string
Notice: Undefined offset: 1455260079 in /in/Eq1OI on line 24
Tracking : #34567808765098767 USPS
Notice the type of the key in of two arrays - the casted array have (numeric) string
keys, while the reassigned array have integer
keys.
When you cast the object to an array, the key is somehow still a string
. This is not expected by the PHP definition of an array, according to the quote above.
So when you try to access the array with a "numeric string", PHP still treats the string
as an integer
, but internally, the keys are still strings, resulting in a undefined array.
This also implies that for associative arrays, key comparisons are actually strict but practically loose.
PHP prepend object in array of objects
You should be able to "simply" merge the two arrays:
$post_types = array_merge($prepend, $post_types);
PHP: convert object to array gives me index of array field's name with namespace?
Instead of converting it to array (which will do things you don't expect), have your MyObject
implement the JsonSerializable interface.
namespace backoffice\controller;
class MyObject implements \JsonSerializable
{
private $id;
private $name;
public function jsonSerialize() {
return get_object_vars($this);
}
// setters
}
Then you can use json_encode
on it directly and get the desired result:
$obj = new MyObject;
$obj->setId(1);
$obj->setName('foo');
echo json_encode($obj); // {"id":1,"name":"foo"}
How do I convert an object to an array?
You should look at get_object_vars , as your properties are declared private you should call this inside the class and return its results.
Be careful, for primitive data types like strings it will work great, but I don't know how it behaves with nested objects.
in your case you have to do something like;
<?php
print_r(get_object_vars($response->response->docs));
?>
PHP - Array to object - Issue when getting object variable by index
This is PHP brokenness. Curly-brace syntax for object property access does not work for all-digit keys.
get_object_vars() vs. cast to array
This is not exactly true.
get_object_vars
is scope-sensitive and will return all visible properties excepting static properties regardless of their visbility. If you call it from outside your class, you'll only get the public members; from a derived class, you'll get the protected and public members; and from the class itself, you'll get all the members. The array keys represent the property names, and are not mangled.
The (array)
cast returns, at least on PHP 5.3.0, all the object properties, public and otherwise. The name of the properties are mangled according to their protection level:
public
: not mangled, identical to property namesprotected
: key name for property starts with a*
private
: key name for property starts with the name of the class
See casting to an array for more informations.
I hope you'll be able to better understand which one is the most appropriate for your situation.
Strange behavior adding this object to this static array
That's because your object (i.e. $this
in internal context) will be copied by reference, not by value. To do copy by value, you'll need to do:
public function add($type, $message)
{
$this->type = $type;
$this->message = $message;
self::$_alerts[] = clone $this;
}
As an alternative, you'll need to instantiate (that is, for example, constructions like new self
- but clone
seems to be more flexible here) your object as many times as you'll wish to copy.
By the way, there's easy way to realize what's going on. Use var_dump()
instead of print_r()
- then you'll see that objects are actually same. Sample for your code (i.e. where copying is not fixed yet):
array(2) {
[0]=>
object(Alert)#1 (2) {
["type":"Alert":private]=>
string(5) "error"
["message":"Alert":private]=>
string(6) "test 2"
}
[1]=>
object(Alert)#1 (2) {
["type":"Alert":private]=>
string(5) "error"
["message":"Alert":private]=>
string(6) "test 2"
}
}
-as you can see, objects are same there.
Casting an array to an object allows invalid property names?
That's done by the cast. And technically spoken, those names are not invalid.
You need to differ how you can write (define) these names. If you write:
$1
That's an invalid label. But if you write
${1}
That label is not invalid.
This question might be interesting for you as well: Array to Object and Object to Array in PHP - interesting behaviour.
Related Topics
Warning: Array_Combine(): Both Parameters Should Have an Equal Number of Elements
Using Fetch_Assoc on Prepared Statements
PHP on Godaddy Linux Shared Trying to Send Through Gmail Smtp
Is MySQLi Extension Enabled in This PHP Configuration
Why a Function Checking If a String Is Empty Always Returns True
How to Remove All Leading Zeroes in a String
Symfony2 Create Own Encoder for Storing Password
File_Exists() Returns False Even If File Exist (Remote Url)
How to Determine a File's True Extension/Type Programmatically
$_Post Is Empty After Form Submit
What Does the MySQLi_Error() Expects Parameter 1 to Be MySQLi, Null Given Mean
Warning: Date() Expects Parameter 2 to Be Long, String Given In