16

I recently saw this line in a PHP piece of code:

$dbObject = json_decode($jsonString);
$dbObject->{'mysql-5.4'}[0]->credentials

What does this mean? In the PHP docs we can read, that

Both square brackets and curly braces can be used interchangeably for accessing array elements (e.g. $array[42] and $array{42} will both do the same thing in the example above).

But how can the Object $dbObject be defined to allow ->{...}[...]access? Is this code kind of unsafe? Which PHP version does allow this?

Did I miss anything in the PHP docs?

WeSee
  • 3,158
  • 2
  • 30
  • 58
  • 1
    Have a look at this http://stackoverflow.com/questions/3737139/reference-what-does-this-symbol-mean-in-php – usrNotFound Oct 01 '15 at 08:45
  • 1
    @Dagon The question set as original does not cover the curly braces syntax. How could that be a duplicate? – feeela Oct 01 '15 at 09:00
  • Does anyone know what version of PHP this was introduced in? –  Oct 01 '15 at 14:49
  • Does anybody have a sample class definition to allow `$dbObject->{'mysql-5.4'}[0]->credentials`? – WeSee Oct 01 '15 at 15:09
  • It's just decoding the JSON string `{"mysql-5.4":[{"credentials":1}]}` (replace `1` with whatever the value of `$dbObject->{'mysql-5.4'}[0]->credentials` is). – Michael Oct 01 '15 at 16:03

5 Answers5

25

It's to enable access to properties which would be invalid syntax as bare literals. Meaning:

$dbObject->mysql-5.4[0]->credentials

This is invalid/ambiguous syntax. To make clear to PHP that mysql-5.4 is a property and not a property minus a float, you need to use the {'..'} syntax.

To be exact, ->{..} enables you to use any expression as the property name. For example:

$dbObject->{ sprintf('%s-%.1f', 'mysql', 5.4) }
deceze
  • 510,633
  • 85
  • 743
  • 889
  • you cannot use `-` for a property. Maybe is a magic property (`__get`) – Luca Rainone Oct 01 '15 at 08:46
  • You cannot use `-` *and a whole host of other characters* like `.` for property names because they do not constitute valid variable names, because they conflict with other characters used for operators. – deceze Oct 01 '15 at 08:50
5

The curly brace syntax allows you to use a string literal or variable as a property or method name.

This is useful for several reasons:

  1. (per @Deceze's answer): It allows you to access property names that would otherwise not be valid PHP syntax -- eg if the property name contains a dot or dash, per your example. Typically properties like this would be accessed via a __get() magic method, since they would also be invalid syntax to define as an actual property within the class.

  2. (per @feela's answer): It allows you to use variables to reference your properties. This is similar to the $$ variable variable syntax. It's generally not really very good practice, but is useful in some cases.

  3. (not mentioned by any other answers yet): It allows you to remove certain potential ambiguities from your code. Consider the following code for example:

    $output = $foo->$bar['baz'];
    

    This is ambiguous. You can resolve the ambiguity by adding braces or brackets:

    $output = $foo->{$bar['baz']};  //gets the value of a property from $foo which has a name that is defined in $bar['baz']
    $output = ($foo->$bar)['baz'];  //gets the ['baz'] element of $foo->$bar array.
    

    This is particularly important because the forthcoming relese of PHP 7 will change the default behaviour of code like like. This will make the language behave more consistently, but will break existing code that doesn't have the braces.

    See also the PHP documentation for this change here: https://wiki.php.net/rfc/uniform_variable_syntax

    But even without the language change to force the issue, code like this should have braces anyway to help with readability -- if you don't put braces, then you may end up struggling to work out what you were trying to do when you come back to the code in six months' time.

Simba
  • 4,952
  • 3
  • 19
  • 29
4

The curly braces syntax in the example is not from the array syntax, but comes from a possible syntax to access variables with variable names.

Curly braces may also be used, to clearly delimit the property name. They are most useful when accessing values within a property that contains an array, when the property name is made of mulitple parts, or when the property name contains characters that are not otherwise valid (e.g. from json_decode() or SimpleXML).

Examples from the PHP docs:

echo $foo->{$baz[1]} . "\n";
echo $foo->{$start . $end} . "\n";
echo $foo->{$arr[1]} . "\n";

See “PHP Variable variables”: http://php.net/manual/en/language.variables.variable.php (More examples on the usage there…)

feeela
  • 29,399
  • 7
  • 59
  • 71
4

As an addition to @deceze's answer:

The -> operator means that you are accessing an object property. In this case the property name should be mysql-5.4 which is not valid PHP identifier (it must contain letters, numbers or underscores, see here). So it is 100% sure that the property name has been created dynamically.

PHP allows overloading properties using magic method called __get(). The body of this method allows you to handle any property you would wish - this can be any string, or any variable, even an object, which is cast to a string.

So in your case somebody created a class with a __get() magic method that handles string mysql-5.4. The curly braces { and } are given to denote that the string should be treated as property name (however there is no property with this name).

Community
  • 1
  • 1
Voitcus
  • 4,463
  • 4
  • 24
  • 40
1

most of the time there is a $ after ->{ so it's like ->$variable

for example we have:

$languageCode = 'en';
$obj->{$languageCode};

$obj->{$languageCode} it is equivalent to $obj->en

============

in your case it's because it's not allowed in php write like:

$dbObject->mysql-5.4

because there is a - and there is a . in the mysql-5.4 and - and . makes a word to two words.

so you have to write it like this:

$dbObject->{'mysql-5.4'}[0]->credentials
Raskul
  • 1,674
  • 10
  • 26