So... This is more of a curiosity, not a real problem. I don't get this:
<?php
define('EMPTY', 1);
echo EMPTY;
Results in: Parse error: syntax error, unexpected ';', expecting '('
My first thought is that empty is reserved for the empty function. But then I tried:
<?php
define('IS_ARRAY', 1);
echo IS_ARRAY;
Result: 1
So... I don't get it. Why empty can't be used as constant while for example is_array, die, etc. can.
empty is not a function but a language construct (more like an operator than a function), which means it's resolved by the parser at parse time and not by the runtime. It's a reserved keyword and you cannot use it for anything yourself like function names, or constants.
The reason empty cannot be a regular function is because it behaves differently. empty($undefined) would first resolve $undefined, throw an error, then pass null to empty; which is exactly the case empty is supposed to prevent, so it cannot play by the normal function invocation rules.
empty is a reserved keyword in PHP. You cannot use any reserved words as constants, class names, function or method names as these words have special meaning in PHP. Use any other name as constant.
You can definately define "EMPTY" as a constant. The problem is you can't use it directly.
<?php
define("EMPTY", "valueForEmpty");
echo EMPTY; // Wont work because empty is a keyword and PHP doesn't know that you mean the constant.
echo constant("EMPTY"); // Works
Note that the reserved keywords are also case insensitive, and they can't be defined as constant or redefined using runkit_function_redefine();
You can find here the exhaustive list of reserved keywords
Related
When setting a namespace to "App\Case" I'm being thrown the following error:
syntax error, unexpected 'Case' (T_CASE), expecting identifier (T_STRING)
Code line in reference:
use App\Case;
Changing the word from "case" to something else fixes this. But from what I understand this is a valid namespace name and should not collide with the reserved keyword 'case' in PHP.
I encountered this issue whilst using Laravel migrations on Homestead CLI, but I don't believe this is relevant to the problem
Is this a bug or an invalid name in the namespace?
They're reserved for a reason because in the first scenario above, PHP wouldn't be able to tell the difference between you defining an array or initialising a class of the same name, so it throws an error. There's no way round this like in MySQL, for example, where you can escape reserved words with a backtick. So in PHP you're forced to change the name, you don't have to change it much, one char will do as long as you're not using the exact same name as a reserved word.
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
I can see in PHP 5.3.2 there is an ArrayObject class. Is it possible to declare a new object named Array
that extends the ArrayObject. But Im not sure if 'Array' is a reserved keyword or should I use my own prefix i.e XArray(), MyArray etc...
What I would like to have is
class Array extends ArrayObject {
...my own code
}
All you'd have to do is try to run:
<?php class Array {}
And you'd see:
Parse error: syntax error, unexpected 'Array'
So the answer is, no, you cannot. You'll need to use a different name.
If it works right now, it may just happen that they do create an Array class in the future. It is best just to stay away from names that are so obviously logical for the language to define.
edit: As Matthew pointed out, it doesn't work. Seeing his answer made me realize why it doesn't work: array is a keyword in php (allowing you to make an array literal) and keywords are case insensitive in php.
Im not sure if 'Array' is a reserved keyword
That's pretty easy to check. PHP's list of reserved keywords has "array()" listed front and center.
That page also lists the following guidance:
You cannot use any of the following words as constants, class names, function or method names. Using them as variable names is generally OK, but could lead to confusion.
So no, you can't. You need to rename your class to something else, and your name must be differentiated by more than just letter-casing since PHP class names are case-insensitive.
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.
I'm trying to get a constant string and index it as if it was an array of characters (square bracket syntax). When I try this code it fails on the last line.
define( 'CONSTANT_STRING','0123456789abcdef');
echo CONSTANT_STRING; // Works by itself :)
$string = CONSTANT_STRING;
echo $string[9]; // Also works by itself.
echo strlen(CONSTANT_STRING); // Also works by itself.
echo substr(CONSTANT_STRING, 9, 1); // Ok, yes this works, but not as clean.
echo CONSTANT_STRING[9]; // Fails as a syntax (parse) error.
I am using a constant string like this in a function. Since it could be called multiple times on one page it really should be a constant. What is the best option if there is no way to do this like I originally intended.
PHP Constants can only be scalar values, so the engine doesn't try to properly parse a constant that's used as something more than a scalar, like an array or an object.
This is a problem in your case because the brackets are used to point at an array index and can be used as a shortcut to grab a character at a specific location in the string.
You'll just have to do it the "hard" way and use substr().