The suggestion to make "namespace php;" implicit is very
interesting, but would defeat its purpose, which is to separate
declarations from use.
Oh, I missed that little wrinkle -- I did say I was only skimming! I guess it could still be done, but at somewhat greater cost in the engine than I was imagining, which probably isn't worthwhile.
Cheers!
Mike
Mike Ford, Electronic Information Services Adviser,
JG125, The Headingley Library,
James Graham Building, Leeds Metropolitan University,
Headingley Campus, LEEDS, LS6 3QS, United Kingdom
Email: m.ford@leedsmet.ac.uk
Tel: +44 113 812 4730 Fax: +44 113 812 3211
To view the terms under which this email is distributed, please go to http://disclaimer.leedsmet.ac.uk/email.htm
Hi Greg,
How about this: any non-namespaced file that uses "use" statements is
implicitly put into the php namespace (or whatever other name is
chosen, or having the namespace name be the path of the file)? With
this, "use" will never import any symbols into the global namespace.
Regards,
Jessie
Ford, Mike wrote:
The suggestion to make "namespace php;" implicit is very
interesting, but would defeat its purpose, which is to separate
declarations from use.Oh, I missed that little wrinkle -- I did say I was only skimming! I guess it could still be done, but at somewhat greater cost in the engine than I was imagining, which probably isn't worthwhile.
Cheers!
Mike
Mike Ford, Electronic Information Services Adviser,
JG125, The Headingley Library,
James Graham Building, Leeds Metropolitan University,
Headingley Campus, LEEDS, LS6 3QS, United Kingdom
Email: m.ford@leedsmet.ac.uk
Tel: +44 113 812 4730 Fax: +44 113 812 3211To view the terms under which this email is distributed, please go to http://disclaimer.leedsmet.ac.uk/email.htm
Jessie Hernandez wrote:
Hi Greg,
How about this: any non-namespaced file that uses "use" statements is
implicitly put into the php namespace (or whatever other name is
chosen, or having the namespace name be the path of the file)? With
this, "use" will never import any symbols into the global namespace.
Hi Jessie,
Imagine how that would affect this code:
file1.php:
<?php
function doSomething() {}
?>
PEAR2/DB.php: <hypothetical>
<?php
namespace PEAR2;
class DB {}
?>
file2.php:
<?php
include 'file1.php';
include 'PEAR2/DB.php';
use PEAR2::DB;
$a = new DB;
$b = doSomething();
?>
In file2.php, because there is a "use" statement, the rest of the file
is assumed to be in the php namespace. As such, the file can be
expanded into this code:
new_file2.php:
<?php
namespace php;
include 'file1.php';
include 'file2.php';
$a = new PEAR2::DB;
$b = doSomething();
?>
On the last line, when PHP calls doSomething(), it first checks to see
if the function "doSomething" is available as an internal function.
Then, it tries php::doSomething() and fails on a fatal error because
the function does not exist. The only way that your idea would work is
if the check for "doSomething" consisted of checking for any
non-namespaced function (not just internal functions), but the sole
purpose of the fall-through is to allow users to call internal
functions/classes without explicitly specifying ::strlen or ::count and
so on. Allowing fall-through to any global class/function would serve
to dilute the namespacing effect, but perhaps this is a good thing? I
have not thought about this long enough to have a definitive opinion yet.
I think one safe way to handle this might be to have an E_STRICT
if
class/function/const is declared in the php namespace, so that PHP
provides a clear mechanism for enforcing the convention. Users wishing
to avoid this E_STRICT
need only use another namespace name or adhere to
the coding convention of only putting stuff that uses code into the
php namespace.
Greg
I thought global names were considered in the patch, but now that I
re-read Dmitry's post, only symbols in the namespace and internal
symbols are considered.
I read through most of the posts regarding namespaces, but could not
find a reason why global names are not looked up. Classes/functions
should first be looked up in the current namespace, if not found, then
they should be looked up in the global namespace, and if it is not found
there either, then there should be a check to see if there is an
internal class/function with the same name.
Dmitry, what's the reason this lookup logic wasn't used in your patch?
Regards,
Jessie
Gregory Beaver wrote:
Jessie Hernandez wrote:
Hi Greg,
How about this: any non-namespaced file that uses "use" statements is
implicitly put into the php namespace (or whatever other name is
chosen, or having the namespace name be the path of the file)? With
this, "use" will never import any symbols into the global namespace.
Hi Jessie,Imagine how that would affect this code:
file1.php:
<?php
function doSomething() {}
?>PEAR2/DB.php: <hypothetical>
<?php
namespace PEAR2;
class DB {}
?>file2.php:
<?php
include 'file1.php';
include 'PEAR2/DB.php';
use PEAR2::DB;
$a = new DB;
$b = doSomething();
?>In file2.php, because there is a "use" statement, the rest of the file
is assumed to be in the php namespace. As such, the file can be
expanded into this code:new_file2.php:
<?php
namespace php;
include 'file1.php';
include 'file2.php';
$a = new PEAR2::DB;
$b = doSomething();
?>On the last line, when PHP calls doSomething(), it first checks to see
if the function "doSomething" is available as an internal function.
Then, it tries php::doSomething() and fails on a fatal error because
the function does not exist. The only way that your idea would work is
if the check for "doSomething" consisted of checking for any
non-namespaced function (not just internal functions), but the sole
purpose of the fall-through is to allow users to call internal
functions/classes without explicitly specifying ::strlen or ::count and
so on. Allowing fall-through to any global class/function would serve
to dilute the namespacing effect, but perhaps this is a good thing? I
have not thought about this long enough to have a definitive opinion yet.I think one safe way to handle this might be to have an
E_STRICT
if
class/function/const is declared in the php namespace, so that PHP
provides a clear mechanism for enforcing the convention. Users wishing
to avoid thisE_STRICT
need only use another namespace name or adhere to
the coding convention of only putting stuff that uses code into the
php namespace.Greg
I agree with this 100%, is this something that could be changed? I don't
see a reason behind it.
internal class/function with the same name.
Dmitry, what's the reason this lookup logic wasn't used in your patch?
Sam Barrow wrote:
I agree with this 100%, is this something that could be changed? I don't
see a reason behind it.internal class/function with the same name.
Dmitry, what's the reason this lookup logic wasn't used in your patch?
Hi,
Actually, there several good reasons. For one, every single unknown
class declaration inside a namespace would require a double check of
class existence, hitting performance.
Here's another example showing the "gotcha" that is inherent:
file1.php:
<?php
namespace Foo;
class IwantThis {}
?>
file2.php:
<?php
class IwantThis {}
?>
file3.php:
<?php
namespace Foo;
include 'file2.php';
function __autoload($class)
{
include 'file1.php'; // stupid but illustrates the point
}
$a = new IwantThis;
?>
Currently, executing file3.php would result in this logic chain:
- does Foo::IwantThis exist? no => step 2
- does internal class IwantThis exist? no => step 3
- try autoloading Foo::IwantThis, loads file1.php, now Foo::IwantThis
exists
If this logic chain were changed to instead check for any globally
defined class of that name, the logic chain would be:
- does Foo::IwantThis exist? no => step 2
- does ::IwantThis class exist? yes => use ::IwantThis
In other words, it would completely break autoloading for namespaced
classes. Of course, this is the same problem as conflicting with
internal classnames, but the scope of the problem is far larger because
there are so few classes internal to PHP, and even fewer that are likely
to conflict with unqualified names.
So, it could be changed (patch attached for 5.3 to prove the concept,
it's not the best way to do this but shows the way it could be done),
but the price would be an absolute requirement that all classes be
explicitly "use"d in some manner inside a namespace.
Greg
Jessie Hernandez wrote:
I thought global names were considered in the patch, but now that I
re-read Dmitry's post, only symbols in the namespace and internal
symbols are considered.I read through most of the posts regarding namespaces, but could not
find a reason why global names are not looked up.
Classes/functions should first be looked up in the current namespace,
right.
if not found, then they should be looked up in the global namespace,
never. I have no idea why do you think they should look there...
and if it is not found
there either, then there should be a check to see if there is an
internal class/function with the same name.
Today all internal classes/functions are in the global namespace.
We allowed usage of internal names in namespaces, because it would be
terrible to prefix each usage of internal function like strlen()
, write().
Dmitry.
Dmitry, what's the reason this lookup logic wasn't used in your patch?
Regards,
Jessie
Gregory Beaver wrote:
Jessie Hernandez wrote:
Hi Greg,
How about this: any non-namespaced file that uses "use" statements is
implicitly put into the php namespace (or whatever other name is
chosen, or having the namespace name be the path of the file)? With
this, "use" will never import any symbols into the global namespace.
Hi Jessie,Imagine how that would affect this code:
file1.php:
<?php
function doSomething() {}
?>PEAR2/DB.php: <hypothetical>
<?php
namespace PEAR2;
class DB {}
?>file2.php:
<?php
include 'file1.php';
include 'PEAR2/DB.php';
use PEAR2::DB;
$a = new DB;
$b = doSomething();
?>In file2.php, because there is a "use" statement, the rest of the file
is assumed to be in the php namespace. As such, the file can be
expanded into this code:new_file2.php:
<?php
namespace php;
include 'file1.php';
include 'file2.php';
$a = new PEAR2::DB;
$b = doSomething();
?>On the last line, when PHP calls doSomething(), it first checks to see
if the function "doSomething" is available as an internal function.
Then, it tries php::doSomething() and fails on a fatal error because
the function does not exist. The only way that your idea would work is
if the check for "doSomething" consisted of checking for any
non-namespaced function (not just internal functions), but the sole
purpose of the fall-through is to allow users to call internal
functions/classes without explicitly specifying ::strlen or ::count and
so on. Allowing fall-through to any global class/function would serve
to dilute the namespacing effect, but perhaps this is a good thing? I
have not thought about this long enough to have a definitive opinion yet.I think one safe way to handle this might be to have an
E_STRICT
if
class/function/const is declared in the php namespace, so that PHP
provides a clear mechanism for enforcing the convention. Users wishing
to avoid thisE_STRICT
need only use another namespace name or adhere to
the coding convention of only putting stuff that uses code into the
php namespace.Greg