php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #77100 Inconsistent behavior between constants and magic constants
Submitted: 2018-11-03 16:12 UTC Modified: 2018-11-05 14:57 UTC
From: fabien dot villepinte at gmail dot com Assigned: cmb (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
4 + 1 = ?
Subscribe to this entry?

 
 [2018-11-03 16:12 UTC] fabien dot villepinte at gmail dot com
Description:
------------
The functions define(), defined() and constant() don't work the same way whether the name of the constant given as an argument is the name of an already defined constant or the name of a magic constant.

For instance :
define('PHP_EOL', 0); // returns false and emits a notice
define('__DIR__', 0); // returns true
__DIR__; // returns the path of the current directory
constant('__DIR__'); // returns the value of the user-defined constant, 0 in this case

There is nothing in the documentation mentioning this case, so I can't say if the current behavior is correct or not.

Test script:
---------------
<?php
var_dump(defined('__LINE__'));
var_dump(define('__LINE__', 'test'));
var_dump(constant('__LINE__'));
var_dump(__LINE__);

Actual result:
--------------
bool(false)
bool(true)
string(4) "test"
int(5)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-11-03 16:26 UTC] nikic@php.net
-Package: PHP Language Specification +Package: Scripting Engine problem
 [2018-11-03 16:54 UTC] cmb@php.net
FWIW, the docs[1] say:

| All these "magical" constants are resolved at compile time,
| unlike regular constants, which are resolved at runtime.

[1] <http://php.net/manual/en/language.constants.predefined.php>
 [2018-11-03 21:27 UTC] a at b dot c dot de
To continue that: Which means that when run time comes around the names are free to be redefined as user constants. But the literal identifiers aren't in the code any more so the only way they can be accessed is through the constant('') construct.

The compile-time evaluation of magic constants also means
define('__DIR__', 0);
is legal, but 
const __DIR__ = 0;
is not, since the latter definition happens at compile time too.

Maybe a check (c|sh)ould be made that users aren't trying to define() magic constants themselves? I'd suggest prepopulating the constants table with them only I don't know how something like constant('__LINE__') could work.
 [2018-11-04 11:21 UTC] cmb@php.net
> I'd suggest prepopulating the constants table with them only I
> don't know how something like constant('__LINE__') could work.

Prepopulating the constants table would require to update it
frequently during run time to be consistent with the compile time
constants.  Besides being inefficient, it would also change
“constant” values.  It might be preferable to not allow any of the
predefined magic constants (or maybe all constant names with two
leading and trailing underscores) to be used with define(),
defined() and constant().  Either way would break BC, though.
 [2018-11-04 12:44 UTC] nikic@php.net
I'm inclined to mark this won't fix. Magic constants are just keywords that have syntactical similarity to constants. I don't think we have any business checking that constant names do not match keywords. If we forbid define('__DIR__'), should we also forbid define('function')?

Ultimately everything here works just fine in the sense that you can define that constant and also look it up using constant(). You can't access it with constant syntax because the __DIR__ keyword takes precedence, but there's any number of other reasons why such an access may not be possible. For example, you can also do define('123', 'foo') and then access it using constant('123'), but for obvious reasons it will not change the behavior of directly writing 123 in code.
 [2018-11-04 14:58 UTC] cmb@php.net
-Type: Bug +Type: Documentation Problem -Assigned To: +Assigned To: cmb
 [2018-11-04 14:58 UTC] cmb@php.net
@nikic Thanks!  Changing to doc problem.
 [2018-11-05 00:11 UTC] a at b dot c dot de
That is consistent with variable names: just as you can create a variable that has a name impossible to use as a literal (e.g., ${"$"}) so too you can create a constant that can't be referred to literally.
 [2018-11-05 14:56 UTC] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=345954
Log: Fix #77100: Inconsistent behavior between constants and magic constants
 [2018-11-05 14:57 UTC] cmb@php.net
-Status: Assigned +Status: Closed
 [2018-11-05 14:57 UTC] cmb@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Nov 19 11:01:30 2019 UTC