php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #74257 "namespace \X" does not work to declare a namespace
Submitted: 2017-03-16 12:47 UTC Modified: 2020-03-13 17:38 UTC
From: david at grudl dot com Assigned: cmb (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 7.1.2 OS:
Private report: No CVE-ID: None
 [2017-03-16 12:47 UTC] david at grudl dot com
Description:
------------
Leading slash in namespace declaration can cause silent ignorance of namespace declaration.

https://3v4l.org/DEZBT

Test script:
---------------
<?php

define('X', 'Y');

namespace \X;

class Test
{
}

echo Test::class;


Expected result:
----------------
Fatal error: Namespace declaration statement has to be the very first statement or after any declare call in the script

Actual result:
--------------
'Test'

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-03-16 16:46 UTC] tpunt@php.net
This is not a bug, but rather a feature in namespaces known as relative names.

In short, the following line:
namespace \X;

is not a namespace *declaration*, but rather an *expression* that resolves to the symbol X of the current namespace. The "namespace \" part (where space is optional) is either evaluated to the currently defined namespace (it is simply ignored for the global namespace).

When utilising this feature, symbols that are not found in the current namespace will not fallback to the globally defined functions or constants.

So, the following works:
var_dump(namespace\PHP_ZTS);

But the following will error (due to an undefined PHP_ZTS constant in the current namespace):
namespace test;
var_dump(namespace\PHP_ZTS);

Whilst obviously the following will work as expected (by falling back to the globally defined PHP_ZTS constant):
namespace test;
var_dump(PHP_ZTS);

See the manual for further information: http://php.net/manual/en/language.namespaces.rules.php
 [2017-03-16 16:46 UTC] tpunt@php.net
-Status: Open +Status: Not a bug
 [2017-03-16 16:46 UTC] tpunt@php.net
^ See above comment...
 [2019-01-31 01:16 UTC] roy-orbison at devo dot net dot au
This is definitely a bug. If PHP devs really think it's a feature, why isn't it documented in "Defining Namespaces"? There is no way anyone would expect the following to be anything other than a definition.

namespace \Foo\Bar;

Accessing members of a namespace relative to global is done with a leading backslash, so why not the same for defining? It should at least be a syntax error rather than evaluate and cause a fatal error or silently fail. That type of expression could only read a constant without doing any assignment, thus have no effect on other userspace state, right? So what's the point of allowing it without even a warning?
 [2019-01-31 01:30 UTC] requinix@php.net
-Summary: Leading slash in namespace declaration +Summary: "namespace \X" does not work to declare a namespace -Status: Not a bug +Status: Open -Type: Bug +Type: Documentation Problem -Package: Compile Failure +Package: Scripting Engine problem
 [2019-01-31 01:30 UTC] requinix@php.net
Keep in mind OP had to define X as a constant. In the real world namespaces have more meaningful names and it's unlikely there will be a constant by the same name, so code would create an error.

Additionally, "namespace\" is documented in "namespace keyword and __NAMESPACE__ constant"
http://php.net/manual/en/language.namespaces.nsconstants.php
 [2019-01-31 22:51 UTC] roy-orbison at devo dot net dot au
Indeed, but that error is not picked up by linting, and the message is for an undefined constant.
 [2020-03-13 16:40 UTC] cmb@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: cmb
 [2020-03-13 16:40 UTC] cmb@php.net
What is supposed to be missing from the documentation?
 [2020-03-13 16:50 UTC] requinix@php.net
-Status: Feedback +Status: Open
 [2020-03-13 16:50 UTC] requinix@php.net
@roy-orbison is saying that
> namespace \Identifier;
should either work as a namespace definition or be a parse error. Because of the space. The former is not possible because it's ambiguous with the namespace\ root, and the latter is not great because it assigns significance to the whitespace that did not exist before.

So I figure we address the problem by adding a quick note to
https://www.php.net/manual/en/language.namespaces.definition.php
docs that says not to use a leading slash when defining a namespace. (Of course, anyone who did so would very quickly realize it didn't work.)
 [2020-03-13 17:37 UTC] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=349407
Log: Fix #74257: &quot;namespace \X&quot; does not work to declare a namespace
 [2020-03-13 17:38 UTC] cmb@php.net
-Status: Assigned +Status: Closed
 [2020-03-13 17:38 UTC] cmb@php.net
Thanks @requinix!
 [2020-03-13 17:38 UTC] phpdocbot@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=59d459d265d56bcfc4e6691bfc277a69b383da84
Log: Fix #74257: &quot;namespace \X&quot; does not work to declare a namespace
 [2020-03-13 20:56 UTC] mumumu@php.net
Automatic comment from SVN on behalf of mumumu
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=349412
Log: Fix #74257: &quot;namespace \X&quot; does not work to declare a namespace
 [2020-03-13 21:00 UTC] phpdocbot@php.net
Automatic comment on behalf of mumumu
Revision: http://git.php.net/?p=doc/ja.git;a=commit;h=118b5c32359378f9b8dac82e0b80ee80203dc23d
Log: Fix #74257: &quot;namespace \X&quot; does not work to declare a namespace
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Oct 26 08:01:22 2020 UTC