PHP expects T_PAAMAYIM_NEKUDOTAYIM? - php

Does anyone have a T_PAAMAYIM_NEKUDOTAYIM?

It’s the double colon operator :: (see list of parser tokens).

It's Hebrew for "double colon".

It’s a name for the :: operator in PHP. It literally means "double colon". For some reason they named it in Hebrew. Check your code syntax, and put a :: where appropriate :-)

From Wikipedia:
In PHP, the scope resolution operator is also called Paamayim
Nekudotayim (Hebrew: פעמיים נקודתיים‎), which means “double colon” in
Hebrew.
The name "Paamayim Nekudotayim" was introduced in the
Israeli-developed Zend Engine 0.5 used in PHP 3. Although it has been
confusing to many developers who do not speak Hebrew, it is still
being used in PHP 5, as in this sample error message:
$ php -r :: Parse error: syntax error, unexpected
T_PAAMAYIM_NEKUDOTAYIM
As of PHP 5.4, error messages concerning the scope resolution operator
still include this name, but have clarified its meaning somewhat:
$ php -r :: Parse error: syntax error, unexpected '::'
(T_PAAMAYIM_NEKUDOTAYIM)
From the official PHP documentation:
The Scope Resolution Operator (also called Paamayim Nekudotayim) or in
simpler terms, the double colon, is a token that allows access to
static, constant, and overridden properties or methods of a class.
When referencing these items from outside the class definition, use
the name of the class.
As of PHP 5.3.0, it's possible to reference the class using a
variable. The variable's value can not be a keyword (e.g. self, parent
and static).
Paamayim Nekudotayim would, at first, seem like a strange choice for
naming a double-colon. However, while writing the Zend Engine 0.5
(which powers PHP 3), that's what the Zend team decided to call it. It
actually does mean double-colon - in Hebrew!

I know Hebrew pretty well, so to clarify the name "Paamayim Nekudotayim" for you, the paraphrased meaning is "double colon", but translated literally:
"Paamayim" means "two" or "twice"
"Nekudotayim" means "dots" (lit. "holes")
In the Hebrew language, a nekuda means a dot.
The plural is nekudot, i.e, dots, which function as vowels
The reason it why it's called Nekudo-tayim is because the suffix "-ayim" also means "two" or "twice", thus :: denotes "two times, two dots", or more commonly known as the Scope Resolution Operator.

This is also coming when you apply a constant in PHP to the empty() function:
if (!empty(SOME_CONSTANT)) {
}
That was my case. I solved it by using this:
$string = SOME_CONSTANT;
if (!empty($string)) {
}

Edit: Unfortunately, as of PHP 8.0, the answer is not "No, not anymore". This RFC was not accepted as I hoped, proposing to change T_PAAMAYIM_NEKUDOTAYIM to T_DOUBLE_COLON; but it was declined.
Note: I keep this answer for historical purposes. Actually, because of the creation of the RFC and the votes ratio at some point, I created this answer. Also, I keep this for hoping it to be accepted in the near future.

This can happen on foreachs when using:
foreach( $array as $key = $value )
instead of
foreach( $array as $key => $value )

For me this happened within a class function.
In PHP 5.3 and above $this::$defaults worked fine; when I swapped the code into a server that for whatever reason had a lower version number it threw this error.
The solution, in my case, was to use the keyword self instead of $this:
self::$defaults works just fine.

This just happened to me in a string assignment using double quotes. I was missing a closing curly on a POST variable...
"for {$_POST['txtName'] on $date";
should have been
"for {$_POST['txtName']} on $date";
I can't explain why. I mean, I see the error that would break the code but I don't see why it references a class error.

This just happened to me in a foreach loop. I had inadvertently typed ($array as $key as $value) and PHP objected to the first as.

Related

Assigning a static variable to another static variable. Why does it throw an error?

Class Test {
private static $one = ['a','b'];
private static $two = Test::$one; // Throws an error
// Error : syntax error, unexpected '$one', expecting 'identifier' or 'class'
}
Why does it throw an error and what is the way here to make $two = $one?
It is a limitation of the PHP compiler and it is explained in the documentation:
Like any other PHP static variable, static properties may only be initialized using a literal or constant before PHP 5.6; expressions are not allowed. In PHP 5.6 and later, the same rules apply as const expressions: some limited expressions are possible, provided they can be evaluated at compile time.
The key statement here is: "provided they can be evaluated at compile time".
From the error message you receive I can tell you are using PHP 5. On PHP 7 the error message was reworded to clearly state the problem. It says "Constant expression contains invalid operations".
The declaration of the first static variable ($one) compiles because you initialize it with a constant expression. ['a','b'] is an array of strings, it can be evaluated at the compile time, everything is fine.
The second static variable ($two) is initialized with a non-constant expression (Test::$one). Test::$one is a variable. You can tell that its value initial value is known at the compile time (see the paragraph above) and the expression can be evaluated at the compile time.
This kind of behaviour requires a deeper analysis of the code at the compile time. It is probably implemented in C++ or Java compilers but these are languages that are compiled only once and the code they generate is stored in a file and executed or interpreted later. The PHP compiler doesn't work this way for a reason. It compiles the script before each execution, that's why it aims to complete the compilation as fast as possible and doesn't put much effort in code analysis and optimizations.
Update:
As #deceze specifies in a comment, the expression Test::$one cannot be evaluated in the declaration of $two because it uses class Test that is not completely defined at this point. Even the compilers of other languages that allow this kind of reference cannot compute the value of Test::$one when they reach the declaration of $two. They need to use a second compilation pass to be able to evaluate it.

Instantiate PHP object with string via factory

This is similar to Can PHP instantiate an object from the name of the class as a string?.
I'm using propel orm with PHP 5.2.17, and I want to store the name of a query class in the database, say "AuthorQuery", then use it to get a query object. There may be a different way to do this with propel, avoding the ::create() factory method. That solution would be welcome, but I'd rather to know if this is even possible with php (I won't be terribly surprised if the answer is "It's not").
Here's the problem. This will work:
$author_class = "Author";
$author = new $author_class();
Using the new keyword a string will get interpreted as the class name.
But I get syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM (that's referring to the ::) when I try to do it using a factory constructor instead:
$author_query_class = "AuthorQuery";
$author_query = $author_query_class::create(); // syntax error at the ::
Do I need an extra $ or something?
It turns out, this is not an issue for PHP 5.3+
Works exactly the way you describe (as far as I remember) with PHP5.3. However, if you still use 5.2, you can use reflection
$x = new ReflectionClass($author_query_class);
$author_query = $x->getMethod('create')->invoke(null);
Or just
$author_query = call_user_func(array($author_query_class, 'create'));
Worth to mention, that this is "much magic" and it will get hard to understand, what happens, when you have many of such constructions.
$author_query=call_user_func("$author_query_class::create");
This has to do with this line:
$author_query_class::create();
It is because (as quoted from the book PHP Master):
The double colon operator that we use for accessing static properties
or methods in PHP is technically called the scope resolution operator.
If there’s a problem with some code containing ::, you will often see
an error message containing T_PAAMAYIM_NEKUDOTAYIM. This simply refers
to the ::, although it looks quite alarming at first! “Paamayim
Nekudotayim” means “two dots, twice” in Hebrew.
You can do something like this in PHP 5.3 and more support is is on the table for PHP 5.4. Before PHP 5.2 you may have to use something like the other answers provided or , gulp, eval().

What is the name of the :: operator?

I am new to PHP, and I am practicing with some online tutorials. I usually encounter the sign :: while going through books, online tutorial or blogs. Even if I check some PHP demo applications I see this operator. I tried to put this sign in Google, but I got unexpected results. I even tried to search it in other forums as well, but I didn't got the right answer. I usually call it a bubble colon, but what is its technical name?
:: is the scope resolution operator (you may sometimes find references to Paamayim Nekudotayim, hebrew for "double colon"). It is used to call static functions of a class, as in
class MyClass {
public static function hi() {
echo "hello, world";
}
}
MyClass::hi();
For more details on classes and objects, refer to the official documentation.
It has the exotic name "Paamayim Nekudotayim", but you may just call it Scope Resolution Operator.
It's called scope resolution operator. More information in Scope Resolution Operator (::) (PHP manual).
A single one is called a colon, so you could search for "php double colon" and would find this:
http://php.net/manual/en/keyword.paamayim-nekudotayim.php
Scope Resolution Operator (::)
Sometimes it is useful to refer to functions and variables in base classes or to refer to functions in classes that have not yet any instances. The :: operator is being used for this.

Why does empty expect T_PAAMAYIM_NEKUDOTAYIM when a non-variable is given?

<?php
define('foo', 'bar');
if (empty(foo)) {
echo 'qux';
}
http://codepad.org/G1TSK1c6
Parse error: syntax error, unexpected ')', expecting T_PAAMAYIM_NEKUDOTAYIM on line 4
I know that empty() only allows variables to be passed as an argument, but why does it expect a T_PAAMAYIM_NEKUDOTAYIM (i.e. ::) when I give it a constant?
The next logical thing the parser wants is a :: because foo is not a variable.
if (empty(foo::$bar)) {
}
Is the only thing, that works when empty() is not passed a variable. Your example is evaluated as empty(bar) where the parser assumes bar to be a class name and now expects a static member variable.
Saw this one while doing some research, although I know this is a bump I thought I would clarify this better.
empty() is not a function, but a language construct. This means that the underlaying parser code is different from that of parsing arguments sent to regular functions or methods. This may seem inconsistent at first when you experience serve error messages like that one, however lets break it down a little.
empty() is expecting to check something thats variable; a constant is not variable so that is not included in the list of possible syntaxes that can be passed to this construct, which makes perfect sense as you would otherwise be doing something illogical (checking for emptiness in a constant value).
The only other possible variables we have in PHP is good old variables and class properties as they are interchangeable, the relevant syntaxes can be represented like this:
<name> ::= [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
<variable> ::= $ <name>
<property> ::= <name> :: <name> || $ <name> :: <name> || $ <name> -\> <name>
This means that if you are passing a constant, PHP will read this as the class name and therefore is expecting the double colon token '::', hence why the error makes perfect sense.
Hope this was somewhat insightful ;-)
I looked into this, tried it on my local PHP installation and guess what? It worked without a hitch (PHP 5.5.6). After trying the same code on different versions of PHP, I found that it does not work on all versions of PHP < 5.5.x and works otherwise.
So then I took to PHP's documentation, more specifically its changelog from 5.4.x to 5.5.x, and found this:
http://www.php.net/manual/en/migration55.new-features.php#migration55.new-features.empty
empty() supports arbitrary expressions
Passing an arbitrary expression instead of a variable to empty() is now supported. For example:
if (empty(TRUE)) {
echo "This will NOT be printed.\n";
}
if (empty(FALSE)) {
echo "This will be printed.\n";
}
The above example will output:
This will be printed.
So if you're running PHP >= 5.5.x, then this will not be a problem.
You can test the code on different versions of PHP using this service: http://sandbox.onlinephpfunctions.com/. I could not, for the life of me, figure out how to save code samples (I always failed the captcha, even though it's dead simple - I think something MAY be broken on their end).
empty() expects variables and not constants. You should use defined() for constants.
Just a though, but I think this error is thrown when parsing the code.
foo, is not a variable, nor a string, therefore, in the context of parsing, the next solution may be class attribute., but it is not because there is no ::, but it should be because constants should not be used here, and it remains to be a class attribute or method.

Is it okay to use array[key] in PHP?

Is it okay to use array without single or double quotion like $array[key]? I thought it is bad because PHP look for constant first if I don't use single or double quotation. One of my colleagues told me that it does not matter.
What do you guys think?
It is not considered as OK -- even if it will work in most cases.
Basically, when PHP sees this :
echo $array[key];
It will search for a constant, defined with define, called key -- and, if there is none, if will take the 'key' value.
But, if there is something like this earlier in your code :
define('key', 'glop');
It will not take
echo $array['key'];
anymore ; instead, it'll use the value of the key constant -- and your code will be the same as :
echo $array['glop'];
In the end, not putting quotes arround the key's name is bad for at least two reasons :
There is a risk that it will not do what you expect -- which is very bad
It might, today...
But what about next week / month / year ?
Maybe, one day, you'll define a constant with the wrong name ;-)
It's not good for performance :
it has to search for a constant, before using 'key'
And, as said in a comment, it generates notices (even if you disable error_reporting and display_errors, the notices/warnings/errors are still generated, even if discarded later)
So : you should not listen to that guy on this point : he is wrong : it does matter.
And if you need some "proof" that's "better" than what people can tell you on stackoverflow, you can point him to this section of the manual, as a reference : Why is $foo[bar] wrong?
This is not okay and to add to what others have said, it will trigger an error in most cases:
8 Notice Use of undefined constant key - assumed 'key' in file: 'index.php' on line 46
See the section in the PHP Manual for "Why is $foo[bar] wrong?" under "Array do's and don'ts" on this page: http://php.net/manual/en/language.types.array.php
This is wrong and will auto-define a constant:
$var = $array[bar];
This usage however is correct:
$var = "string $array[bar] ...";
For compatibility with PHP2 this old syntax is still allowed in string context. Quoting the key would lead to a parse error, unless you also use { curly braces } around it.
From the PHP Manual - Why is $foo[bar] wrong?
Always use quotes around a string literal array index. For example, $foo['bar'] is correct, while $foo[bar] is not. But why? It is common to encounter this kind of syntax in old scripts:
<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>
This is wrong, but it works. The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes). PHP may in future define constants which, unfortunately for such code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.
There is some more examples in the manual for you to check out.
Unless the key actually is a constant, there is no reason for you not to be putting quotes around the key.
The way PHP works is it looks for the constant value of what you've put, but it takes the string representation of it if the constant cannot be found.
If someone were to edit your code down the road and add a constant with that key name, it would just cause more headaches.
It's bad practice to not quote key values, for a number of reasons:
Potential collisions with meaningful symbol names, such as define'd constants.
Some keys can't be expressed without quoting (for instance, the key "]").
Bad habits can bite you later on (namely in regards to #1 and #2).
Performance - searching for define's takes time.
If you're wanting to avoid typing quotes around names that are just standard elements of a thing you're passing around a lot, perhaps you might want to use objects instead, which take a object->property syntax instead of an $array["element"] syntax.

Categories