First question on SO and it's a real RTM candidate. But I promise you I've looked and can't seem to find it. I'll happily do a #headpalm when it turns out to be a simple thing that I missed.
Trying to figure out Zend Framework and came across the following syntax:
$this->_session->{'user_id'}
I have never seen the curly braces syntax used to access what appears to be a member variable. How is it different than
$this->_session->user_id
I'm assuming that the _session is irrelevant, but including it in the question since it may not be.
Are the curly braces just a cleanliness convention that attempts to wrap the compound variable name user_id? Or is it some kind of a special accessor?
Any pointers into TFM so I can R up would be humbly appreciated.
Many thanks. Please be gentle.
Curly braces are used to explicitly specify the end of a variable name. For example:
echo "This square is {$square->width}00 centimeters broad.";
So, your case is really a combination of two special cases. You're allowed to access class variables using curly braces and like so:
$class->{'variable_name'} // Same as $class->variable_name
$class->{'variable' . '_name'} // Dynamic values are also allowed
And in your case, you're just surrounding them with the curly brace syntax.
See the PHP manual, "complex (curly) syntax."
I know the syntax just when using variable variables:
$userProp = 'id';
$this->_session->{'user_'.$userProp};
Theres probably one big advantage of that syntax, however, its generally in the domain of hairy stuff, and things you probably want to avoid.
It permits you to use characters in variable names that are otherwise unpermitted.
ie:
$this->object->{"hello world\0\n"}
$this->object->{"function(){ this is a truely awful name for a variable }"}
In the example you give, there's no real difference, and IMO $this->_session->user_id should be used because it's clearer.
What the curly brace syntax is actually good for is accessing a member variable by constructing an expression for its name, like $this->_session->{'user_id' . $index}.
The two examples in your question do the same thing. PHP allows you to access member data/methods in several ways...
object->{'name_of_member'};
object->name_of_member;
$member = 'name_of_member';
object->$member;
Related
I've just downloaded an official API OAuth library of a well-known brand from GitHub, and am poking around the code to see how I'm going to call it from our application. The code looks, well, not so great let's say. I've run into this syntax in the code, and to me it looks weird.
There is a class which has the property $this->_secrets, which is an array, I can see that in the code. I would expect if you wanted to set the key consumer_key you would use the syntax:
$this->_secrets['consumer_key']=$APIKey;
Instead they have used the following syntax:
$this->_secrets{'consumer_key'}=$APIKey;
I can't see how this is any different when it comes to how PHP interprets it - I thought use of curly braces was when you wanted to use a variable value as a property name.
Can anyone shed light on why you'd use the second syntax rather than the first?
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
Is it possible to enclose code fragments in PHP within brackets (without using the fragment as a function)?
Would the following code behave the same way as it would without the curly brackets? Or might there be any problems depending on what kind of code used inside or outside the brackets?
For example, will this:
<?php
// First Code-Block
{# several lines of code
}
// Second Code-Block
{# another several lines of code
}
?>
Always behave the same way as this:
<?php
// First Code-Block
# several lines of code
// Second Code-Block
# another several lines of code
?>
Update:
One of the goals, as stated in "My1"'s comment as well, is to structure large code sections. Especially since most IDEs give you the option to collapse the lines between the brackets.
Especially in consideration of "dragondreamer"'s "Luke Mills"'s answers I played around with it a bit, and so far I didn't encounter any side effects. Of course, this might change with new PHP Versions in the future but "Luke Mills"'s answer gives good pointers on what to keep an eye on.
Yes, but it won't create a new local scope. It's not something that would normally be done. Usually people mark blocks like this with comments.
Update:
It took a bit of digging to find a reference to it in the manual, but here it is:
http://www.php.net/manual/en/control-structures.intro.php
Any PHP script is built out of a series of statements. A statement can be an assignment, a function call, a loop, a conditional statement or even a statement that does nothing (an empty statement). Statements usually end with a semicolon. In addition, statements can be grouped into a statement-group by encapsulating a group of statements with curly braces. A statement-group is a statement by itself as well. The various statement types are described in this chapter.
The key here is statements can be grouped into a statement-group by encapsulating a group of statements with curly braces.
I also had a look for a reference to variable scope as it relates to this situation, but the manual doesn't specifically mention it, however you can think of it like this:
In PHP, functions and classes create a variable scope. You can read about that here. But a statement-group (as described above) does not. Don't think of the curly braces of a statement-group like the function (or class) wrapping brackets, but think of them like the curly braces that wrap the statement-group of control structures (if, for, while, switch, etc.) - because that's exactly what they are. It's clear that if you're using an if statement (or any other control structure) that the braces don't introduce a new scope, they are simply wrappers for a block of statements.
PHP code behavior does not change if you enclose it within curly brackets. However, you can't use some PHP statements inside curly brackets:
namespace declarations;
namespace use declarations to alias or import any names;
global const declarations;
__halt_compiler().
This means, the following script will work:
<?php
const x = 5;
echo x;
but the following will not compile:
<?php
{
const x = 5;
echo x;
}
In one project I'm working on, I use statement-groups to indicate structure - in my case, parent/child relationships between nodes creates in a router:
$router = new Router();
$admin = $router->route('admin');
{
$upload = $admin->route('upload')->post('upload');
$menu = $admin->route('menu');
{
$menu->route('load')->get('load');
$menu->route('save')->get('save');
}
}
```
Internally, this builds a hierarchical structure like:
/admin
/upload
/menu
/load
/save
Calling route() in this example creates a child - so the code creates a model (inside the router) which has a tree structure, but the structure of the code does not reflect that.
I'm using curly braces here to make the code more legible, since reading the code without curly braces and indentation would be quite difficult:
$router = new Router();
$admin = $router->route('admin');
$upload = $admin->route('upload')->post('upload');
$menu = $admin->route('menu');
$menu->route('load')->get('load');
$menu->route('save')->get('save');
Indentation in this case really clarifies what's happening, I think.
I also do this, solely because of my text editor (Komodo Edit 8.5). It's not a "bad reason" or "bad coding", if it helps you and doesn't cause any problems and if there's no other easy way to do it.
I solve the problem with a work-around:
if(1 == 1){ //always executing if function
//whatever you want to add
}
#
adding a # at the end prevents my editor from collapsing all empty lines below the curly brackets. This helps to further structure the code.
Is it possible to enclose code fragments in PHP within brackets (without using the fragment as a function)?
Would the following code behave the same way as it would without the curly brackets? Or might there be any problems depending on what kind of code used inside or outside the brackets?
For example, will this:
<?php
// First Code-Block
{# several lines of code
}
// Second Code-Block
{# another several lines of code
}
?>
Always behave the same way as this:
<?php
// First Code-Block
# several lines of code
// Second Code-Block
# another several lines of code
?>
Update:
One of the goals, as stated in "My1"'s comment as well, is to structure large code sections. Especially since most IDEs give you the option to collapse the lines between the brackets.
Especially in consideration of "dragondreamer"'s "Luke Mills"'s answers I played around with it a bit, and so far I didn't encounter any side effects. Of course, this might change with new PHP Versions in the future but "Luke Mills"'s answer gives good pointers on what to keep an eye on.
Yes, but it won't create a new local scope. It's not something that would normally be done. Usually people mark blocks like this with comments.
Update:
It took a bit of digging to find a reference to it in the manual, but here it is:
http://www.php.net/manual/en/control-structures.intro.php
Any PHP script is built out of a series of statements. A statement can be an assignment, a function call, a loop, a conditional statement or even a statement that does nothing (an empty statement). Statements usually end with a semicolon. In addition, statements can be grouped into a statement-group by encapsulating a group of statements with curly braces. A statement-group is a statement by itself as well. The various statement types are described in this chapter.
The key here is statements can be grouped into a statement-group by encapsulating a group of statements with curly braces.
I also had a look for a reference to variable scope as it relates to this situation, but the manual doesn't specifically mention it, however you can think of it like this:
In PHP, functions and classes create a variable scope. You can read about that here. But a statement-group (as described above) does not. Don't think of the curly braces of a statement-group like the function (or class) wrapping brackets, but think of them like the curly braces that wrap the statement-group of control structures (if, for, while, switch, etc.) - because that's exactly what they are. It's clear that if you're using an if statement (or any other control structure) that the braces don't introduce a new scope, they are simply wrappers for a block of statements.
PHP code behavior does not change if you enclose it within curly brackets. However, you can't use some PHP statements inside curly brackets:
namespace declarations;
namespace use declarations to alias or import any names;
global const declarations;
__halt_compiler().
This means, the following script will work:
<?php
const x = 5;
echo x;
but the following will not compile:
<?php
{
const x = 5;
echo x;
}
In one project I'm working on, I use statement-groups to indicate structure - in my case, parent/child relationships between nodes creates in a router:
$router = new Router();
$admin = $router->route('admin');
{
$upload = $admin->route('upload')->post('upload');
$menu = $admin->route('menu');
{
$menu->route('load')->get('load');
$menu->route('save')->get('save');
}
}
```
Internally, this builds a hierarchical structure like:
/admin
/upload
/menu
/load
/save
Calling route() in this example creates a child - so the code creates a model (inside the router) which has a tree structure, but the structure of the code does not reflect that.
I'm using curly braces here to make the code more legible, since reading the code without curly braces and indentation would be quite difficult:
$router = new Router();
$admin = $router->route('admin');
$upload = $admin->route('upload')->post('upload');
$menu = $admin->route('menu');
$menu->route('load')->get('load');
$menu->route('save')->get('save');
Indentation in this case really clarifies what's happening, I think.
I also do this, solely because of my text editor (Komodo Edit 8.5). It's not a "bad reason" or "bad coding", if it helps you and doesn't cause any problems and if there's no other easy way to do it.
I solve the problem with a work-around:
if(1 == 1){ //always executing if function
//whatever you want to add
}
#
adding a # at the end prevents my editor from collapsing all empty lines below the curly brackets. This helps to further structure the code.
I just stumbled upon an interesting syntax in a PHP script:
echo $foo->{'bar'};
$foo in this case is an object returned from PHP's json_decode() function, but it works well when accessing public members of any object.
I've tried to find out why this syntax was used instead of the more common:
echo $foo->bar;
Does accessing a class member with the syntax from the first example offer anything special, compared to the second example?
The curly bracket syntax is useful when you want to reference a function name as a string:
print $foo->{'aMemberFunc'}();
When you want access members which name is provided by another function (or a variable).
Here getVarName() returns a string which can be used to reference a member inside the $foo object.
print $foo->{getVarName()};
Without the curly brackets it would be $foo->getVarName() and it would try and run that method... with the curly brackets it takes a completely different meaning.
echo $foo->{'bar'}; and echo $foo->bar; are identical as far as I can tell.
first syntax allows you to access properties with '-', often used in JSON.
The benefit is that you can have variables names that don't adhere to the rules for naming member variables.
This might seem like a bad idea and usually it is but there are uses for it. An example would be if you were writing an application that allowed its users to add arbitrary fields with human readable names but still be accessible for plugins etc.