views:

200

answers:

2

I was poking around PHPs casting mechanism, and ran into an odd case when casting an array as an object

$o = (object) array('1'=>'/foo/bar'); 
$o = new stdClass();
var_dump($o);

As I understand it, PHP properties need to be declared with the same rules as PHP variables. That is A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. However, the above code produces the following output

object(stdClass)#1 (1) {
  [1]=>
  string(8) "/foo/bar"
}

Where it gets really weird is when you try to access that information in the object.

var_dump($o->1);   // parse error
var_dump($o->{'1'});   // NULL 
var_dump(get_object_vars($o));  //array(0) { }

Is there anyway to get at the the information that var_dump reports is in the object, or is it just locked up for the rest of the request life cycle? (practical use of this is nil, I'm just curious)

+5  A: 

Yes, they are just locked away unless cast back to an array. There are a few little "Gotchas" in PHP, for example in older versions you could define a constant as an array, but then never access its elements. Even now you can define a constant as a resource (e.g., define('MYSQL',mysql_connect());) although this leads to rather unpredictable behavoir and, again, should be avoided.

Generally, it's best to avoid array-to-object casts if at all possible. If you really need to do this, consider creating a new instance of stdClass and then manually renaming all the variables, for example to _0, _1, etc.

$a = array('cat','dog','pheasant');
$o = new stdClass;
foreach ($a as $k => $v) {
    if (is_numeric($k)) {
        $k = "_{$k}";
    }
    $o->$k = $v;
}

EDIT: Just did one more quick test on this hypothesis, and yes, they officially "do not exist" in object context; the data is stored, but it's impossible to access, and is therefore the ultimate private member. Here is the test:

$a = array('one','two','three');
$o = (object)$a;
var_dump(property_exists($o, 1), property_exists($o, '1'));

And the output is:

bool(false)
bool(false)

EDIT AGAIN: Interesting side-note, the following operation comes back false:

$a = array('one','two','three','banana' => 'lime');
$b = array('one','two','banana' => 'lime');

$y = (object)$a;
$z = (object)$b;

var_dump($y == $z);
Dereleased
A: 

I think you get an error because casting an integer key of an array to an object / subobject will break the naming conventions of PHP varibles.

Tips:

  • Decide before hands whether you want to have an OBJECT or an ARRAY
  • Be careful with type casting (e.g. (object) array(1=>'string') do not do such things)
  • Use castings for validation and not to convert things
  • Avoid using objects as "fake" arrays
daemonfire300