PHP operator '->' $foo-> {''} - php

I noticed that on php with the JSON lib we can access an element with a syntax I haven't seen before.
$jsonObject->{'myvar'}; // return the value of myvar on the jsonobject
What this statement mean?

I do not think it is inherent with the JSON lib.
It's just another way to determine the name of the variable you want to call. For example, it's useful when you want to decide dynamically which variable should be called, something that is of great use in magic methods.
$var->{"var_name"} is the equivalent of $var->var_name.
You can do things like these as well:
$key = "key_name";
var_dump($object->{$key});
You can also access keys with invalid characters such as dots or commas.
$key = "key.name.nice";
var_dump($object->{$key});

Related

Fatal error: Uncaught Error: Function name must be a string in... when upgrading to php 7.0 [duplicate]

I have object properties in my code that look like this:
$obj ->field_name_cars[0];
$obj ->field_name_clothes[0];
The problem is I have 100s of field names and need to write the property name dynamically. Otherwise, the object name and the keys for the property will always be the same. So I tried:
$obj -> $field[0];
Hoping that the name of the property would dynamically be changed and access the correct values. But, I keep getting 'undefined property $field in stdClass::$field;
More or less I am trying dynamically write the php before it executes so that it can output the proper values. Thoughts on how to approach this?
Update for PHP 7.0
PHP 7 introduced changes to how indirect variables and properties are handled at the parser level (see the corresponding RFC for more details). This brings actual behavior closer to expected, and means that in this case $obj->$field[0] will produce the expected result.
In cases where the (now improved) default behavior is undesired, curly braces can still be used to override it as shown below.
Original answer
Write the access like this:
$obj->{$field}[0]
This "enclose with braces" trick is useful in PHP whenever there is ambiguity due to variable variables.
Consider the initial code $obj->$field[0] -- does this mean "access the property whose name is given in $field[0]", or "access the element with key 0 of the property whose name is given in $field"? The braces allow you to be explicit.
I think you are looking for variable-variable type notation which, when accessing values from other arrays/objects, is best achieved using curly bracket syntax like this:
$obj->{field[0]}
The magic method __get is you friend:
class MyClass
{
private $field = array();
public function __get($name)
{
if(isset($this->field[$name]))
return $this->field[$name];
else
throw new Exception("$name dow not exists");
}
}
Usage:
$myobj = new MyClass();
echo $myobj->myprop;
Explanation: All your field data is stored in a array. As you access $myobj->myprop that property obviously does not exists in the class. That is where __get is called. __get looks up the name in the field array and returns the correct value.
today i face that challenge. I ended up with that style of development
$countTickets = new \stdClass;
foreach ($tickets as $key => $value) {
if(!isset($countTickets->total)){
$countTickets->total = 0;
}
if(!isset($countTickets->{$value['categoryname']})){
$countTickets->{$value['categoryname']} = 0;
}
$countTickets->total += $value['number'];
$countTickets->{$value['categoryname']} += $value['number'];
}
I worked on some code that used dynamically created object properties. I thought that using dynamically created object properties was pretty cool (true, in my opinion). However, my program took 7 seconds to run. I removed the dynamic object properties and replaced them object properties declared as part of each class (public in this case). CPU time went from over 7 seconds to 0.177 seconds. That's pretty substantial.
It is possible that I was doing something wrong in the way I was using dynamic object properties. It is also possible that my configuration is broken in some way. Of course, I should say that I have a very plain vanilla PHP configuration on my machine.

What is a dereferencable scalar in PHP?

Recently, I was following this PHP talk See it on YouTube. There is a part about new features in PHP7 that is a really strange stuff for me (in "Uniform variable syntax" part of the talk), which wrote:
// support all operations on dereferencable scalars
// (not very useful)
"string"->toLower()
What is a dereferencable scalar? I know when I call a method on a non-object, for example:
echo "string"->toLower();
I'll get the following Error in PHP7:
Fatal Error: Uncaught Error: Call to a member function toLower() on string
Also, I cannot find a way to declare methods on strings (like something we see in JavaScript); as I know, there is no way to do it.
So, what is the code above saying? How can we do the stuff above? What is the use case for it? Saying it generally, what is "string"->toLower()?
(Editted) Note: While the PHP talks says it exists as of PHP 7.0, it seems to be a mistake by Mr. Lerdorf (it could be a rejected patch, for example).
Thanks in advance.
Short answer: this would be a syntax sugar.
Longer answer: This is a way to call functions with the syntax which aligns with the object syntax.
For example, an object (i.e. a class instance) could have a method called "length()". The invocation of this method would be expressed with the following "arrow" syntax:
$length = $myObject->length();
But, for example, to get a length of a string, you can't currently use the same syntax, because strings are not objects. Instead, you must put the variable name within the parentheses, as a parameter to the strlen function , i.e.:
$length = strlen($myString);
What you have mentioned is an idea to unify the syntax, i.e.
$length = $myString->strlen();
would be another possible syntax to call the strlen function. This would make operations on scalars (and arrays) syntactically closer to the objects' method calls.
Note that PHP doesn't support this syntax yet, as of 2018-09-14.

How do I access the contents of this variable in PHP?

I am using a library, XCRUD, which takes a string argument and is expecting a variable interpolation pattern. Here is how it is used in the documentation, which works fine.
$xcrud->column_pattern('username','My name is {value}');
I want to use this variable as a key to an array, but I can't figure out what syntax is required to access it.
I have tried the following:
$xcrud->column_pattern('PlanNo', $myArray['{value}']);
$xcrud->column_pattern('PlanNo', $myArray[eval('{value}')]);
$xcrud->column_pattern('PlanNo', $myArray[${value}]);
How is it that the function in the library I'm calling can access the variable through {}? Maybe it's unreasonable for me to expect it will exist in the current scope, and it just passes that string somewhere down the line.
Thanks for your help. :)
Try this
$xcrud->column_pattern('PlanNo', $myArray[eval("(" + value + ")")]);

What does PHP operator ->{...} mean?

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?
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) }
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:
(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.
(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.
(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.
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…)
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).
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

How do I dynamically write a PHP object property name?

I have object properties in my code that look like this:
$obj ->field_name_cars[0];
$obj ->field_name_clothes[0];
The problem is I have 100s of field names and need to write the property name dynamically. Otherwise, the object name and the keys for the property will always be the same. So I tried:
$obj -> $field[0];
Hoping that the name of the property would dynamically be changed and access the correct values. But, I keep getting 'undefined property $field in stdClass::$field;
More or less I am trying dynamically write the php before it executes so that it can output the proper values. Thoughts on how to approach this?
Update for PHP 7.0
PHP 7 introduced changes to how indirect variables and properties are handled at the parser level (see the corresponding RFC for more details). This brings actual behavior closer to expected, and means that in this case $obj->$field[0] will produce the expected result.
In cases where the (now improved) default behavior is undesired, curly braces can still be used to override it as shown below.
Original answer
Write the access like this:
$obj->{$field}[0]
This "enclose with braces" trick is useful in PHP whenever there is ambiguity due to variable variables.
Consider the initial code $obj->$field[0] -- does this mean "access the property whose name is given in $field[0]", or "access the element with key 0 of the property whose name is given in $field"? The braces allow you to be explicit.
I think you are looking for variable-variable type notation which, when accessing values from other arrays/objects, is best achieved using curly bracket syntax like this:
$obj->{field[0]}
The magic method __get is you friend:
class MyClass
{
private $field = array();
public function __get($name)
{
if(isset($this->field[$name]))
return $this->field[$name];
else
throw new Exception("$name dow not exists");
}
}
Usage:
$myobj = new MyClass();
echo $myobj->myprop;
Explanation: All your field data is stored in a array. As you access $myobj->myprop that property obviously does not exists in the class. That is where __get is called. __get looks up the name in the field array and returns the correct value.
today i face that challenge. I ended up with that style of development
$countTickets = new \stdClass;
foreach ($tickets as $key => $value) {
if(!isset($countTickets->total)){
$countTickets->total = 0;
}
if(!isset($countTickets->{$value['categoryname']})){
$countTickets->{$value['categoryname']} = 0;
}
$countTickets->total += $value['number'];
$countTickets->{$value['categoryname']} += $value['number'];
}
I worked on some code that used dynamically created object properties. I thought that using dynamically created object properties was pretty cool (true, in my opinion). However, my program took 7 seconds to run. I removed the dynamic object properties and replaced them object properties declared as part of each class (public in this case). CPU time went from over 7 seconds to 0.177 seconds. That's pretty substantial.
It is possible that I was doing something wrong in the way I was using dynamic object properties. It is also possible that my configuration is broken in some way. Of course, I should say that I have a very plain vanilla PHP configuration on my machine.

Categories