13
$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?

ORM
  • 465
  • 1
  • 4
  • 8

4 Answers4

7

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
  • 643,351
  • 109
  • 780
  • 844
  • 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 Feb 21 '10 at 17:26
  • Oh,maybe it's not a syntax,hopefully a feature,can you figure out how to implement this kind of feature? – ORM Feb 21 '10 at 17:27
  • @Tatu Ulmanen: `[]` is used on the array. But I don’t know why `[]->` is creating a new object. – Gumbo Feb 21 '10 at 17:28
  • @ORM: Where did you find this? – Sampson Feb 21 '10 at 17:28
  • I've posted a working example of this. But I have never seen this before either. – poke Feb 21 '10 at 17:28
  • Interesting syntax too. I didn't know the stdClass could be instanced that way. I'm curious -how- and -why- this works. – Xorlev Feb 21 '10 at 17:32
  • This even works without an array, when just accessing a property with object `->` syntax. – poke Feb 21 '10 at 17:34
6

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
  • 369,085
  • 72
  • 557
  • 602
  • This is amazing!Can you explain why? – ORM Feb 21 '10 at 17:32
  • 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 Feb 21 '10 at 17:35
  • 1
    Will raise an E_STRICT notice though: *Strict Standards: Creating default object from empty value* – Gordon Feb 21 '10 at 17:39
  • *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 Feb 21 '10 at 17:51
2

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.

user187291
  • 53,363
  • 19
  • 95
  • 127
1

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
  • 312,688
  • 75
  • 539
  • 559