views:

159

answers:

4
$user->Phonenumbers[]->phonenumber = '123 123';
$user->Phonenumbers[]->phonenumber = '456 123';
$user->Phonenumbers[]->phonenumber = '123 777';

I've never seen this kind of syntax

EDIT

This seems more probably a feature,do you guys know how can I implement a feature like this?

+7  A: 

It seems that something like the following creates an stdClass object with the property phonenumber and pushes it into the $user->Phonenumbers array:

$user->Phonenumbers[]->phonenumber = 12345;

I’ve never seen that syntax too.

Gumbo
If Phonenumbers is an array, how can you use the `->` notation on that? Compare to `$foo = array(); $foo->test = 12345;` results in a warning.
Tatu Ulmanen
Oh,maybe it's not a syntax,hopefully a feature,can you figure out how to implement this kind of feature?
ORM
@Tatu Ulmanen: `[]` is used on the array. But I don’t know why `[]->` is creating a new object.
Gumbo
@ORM: Where did you find this?
Jonathan Sampson
I've posted a working example of this. But I have never seen this before either.
poke
Interesting syntax too. I didn't know the stdClass could be instanced that way. I'm curious -how- and -why- this works.
Xorlev
This even works without an array, when just accessing a property with object `->` syntax.
poke
+6  A: 

Gumbo is right, here is a working example:

<?php
class Test
{
    public $arr = array();
    public $obj = null;
}
$a = new Test();
$a->arr[]->foo = 1234;
$a->arr[]->bar = 'test';
var_dump( $a->arr );

// even more weird on null objects
$a->obj->foobar = 'obj was null!';
var_dump( $a->obj );

returns:

array(2) {
  [0]=>
  object(stdClass)#2 (1) {
    ["foo"]=>
    int(1234)
  }
  [1]=>
  object(stdClass)#3 (1) {
    ["bar"]=>
    string(4) "test"
  }
}
object(stdClass)#4 (1) {
  ["foobar"]=>
  string(13) "obj was null!"
}

edit: Okay, I found something related in the php manual about this:

If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created. If the value was NULL, the new instance will be empty. (source)

So using the -> syntax converts the thing into an object. In the example above $obj is null, so a new, empty instance is created, and the foobar member is set.

When looking at the array example, arr[] first creates a new (empty) array element, which is then converted into an empty object because of the -> syntax and the member variable is set.

poke
This is amazing!Can you explain why?
ORM
Given that it even works with null objects (2nd part of the example), it does make sense, that the array creation with `[]` results in this. But I don't know why you can even access a non-existing object and create it on-the-fly with that.
poke
Will raise an E_STRICT notice though: *Strict Standards: Creating default object from empty value*
Gordon
+1 I think that’s it!
Gumbo
*Converting NULL to an array results in an empty array.* See http://de.php.net/manual/en/language.types.array.php - so basically, PHP converts NULL by operator context.
Gordon
+2  A: 

php "implicitly" creates arrays and objects when using [] and -> operators on undefined variables.

 $does_not_exist->foo = 1;

here php creates a stdclass object and throws an "strict" warning "Creating default object from empty value". The similar thing with arrays

 $does_not_exist[] = 1;

oddly works without a warning, which some people consider to be a bug.

stereofrog
+1  A: 

PHP will typecast NULL to the context in which it is used.

var_dump( (bool) NULL );
var_dump( (int) NULL );
var_dump( (float) NULL );
var_dump( (string) NULL );
var_dump( (array) NULL );
var_dump( (object) NULL );

will give

bool(false)
int(0)
float(0)
string(0) ""
array(0) {}
object(stdClass)#1 (0) {}

Consequently, when doing:

$a = NULL;
$a[] = NULL;       // used in array context `[]`
$a[0]->foo = NULL; // object context `->`
$a[0]->foo++;      // number context `++`

the resulting structure will be

array(1) {
  [0]=>
  object(stdClass)#1 (1) {
    ["foo"]=>
    int(1)
  }
}

Like I mentioned in the comments, doing so is against E_STRICT standards though and will raise a notice.

Gordon