Hi,
I recently started porting an application to PHP 5.3.
- While testing the new namespace implementation I noticed the
following:
<?php
namespace Test1;
function fooBar() { echo 'Test1::fooBar()' . PHP_EOL; }
namespace Test2;
use Test1;
Test1::fooBar();
Executing the code above results in a warning: "The use statement with
non-compound name 'Test1' has no effect in [...]".
I understand the rationale behind this warning but it simply isn't
true: omitting the use statement results in a fatal error: "Class
'Test2::Test1' not found in [...]".
Since the following code executes without warning or error I think the
code above (without use statement) should also execute just fine.
<?php
namespace Test1::Test2;
function fooBar() { echo 'Test1::Test2::fooBar()' . PHP_EOL; }
namespace Test3;
Test1::Test2::fooBar();
But I'm not quite sure about the warning (about the non-compound use
statement): I think the warning should either be dropped or its
statement should be fulfilled.
-
I'm sorry for bringing this up again: The current name resolution
order makes using the namespace feature in conjunction with
autoloading less usable and somewhat error prone.a. To avoid that internal classes introduced to PHP somewhen in
the future break my app I've to add a number of use statements that
would not be necessary otherwise.
So to be on the safe side one has to
i. "use" all classes from the current namespace which is
annoying and especially in bigger projects one might easily forget to
"use" classes when making changes
ii. use exactly one file per namespace (this might work
well especially with few classes per namespace that are mostly used
together,
but one can easily think of a lot of situations you
want to load just the classes that are really needed and in the end
this is what autoload is for)
iii. avoid the usage of autoloadb. Applications might behave differently when packaged
i. one class per file using autoload (without "use"-ing
classes from the current namespace)
ii. all classes in one filec. Implementors of autoloaders can keep the performance hit to a
minimum using some kind of caching.
I think the current resolution order is a WTF-factor especially for
unexperienced users or users coming from other languages.
I know that the above arguments might have been already on this list
but I couldn't find some definitive decision to keep the current name
resolution order. If I've missed that I'm sorry for the noise.
Regards,
Julian Reich
Julian,
Regarding the name resolution rules, I posted a patch a few months ago
with what I think is a more reasonable lookup order
(http://news.php.net/php.internals/34097), but did not get much
feedback. Would you like to try it out? (let me know if it doesn't apply
cleanly against the current PHP_5_3)
Regards,
Jessie Hernandez
Zend Certified Engineer (http://zend.com/zce.php?c=ZEND006359&r=222727282)
Julian Reich wrote:
Hi,
I recently started porting an application to PHP 5.3.
- While testing the new namespace implementation I noticed the following:
<?php
namespace Test1;
function fooBar() { echo 'Test1::fooBar()' . PHP_EOL; }namespace Test2;
use Test1;
Test1::fooBar();Executing the code above results in a warning: "The use statement with
non-compound name 'Test1' has no effect in [...]".
I understand the rationale behind this warning but it simply isn't true:
omitting the use statement results in a fatal error: "Class
'Test2::Test1' not found in [...]".Since the following code executes without warning or error I think the
code above (without use statement) should also execute just fine.<?php
namespace Test1::Test2;
function fooBar() { echo 'Test1::Test2::fooBar()' . PHP_EOL; }namespace Test3;
Test1::Test2::fooBar();But I'm not quite sure about the warning (about the non-compound use
statement): I think the warning should either be dropped or its
statement should be fulfilled.
I'm sorry for bringing this up again: The current name resolution
order makes using the namespace feature in conjunction with autoloading
less usable and somewhat error prone.a. To avoid that internal classes introduced to PHP somewhen in the
future break my app I've to add a number of use statements that would
not be necessary otherwise.
So to be on the safe side one has to
i. "use" all classes from the current namespace which is
annoying and especially in bigger projects one might easily forget to
"use" classes when making changes
ii. use exactly one file per namespace (this might work well
especially with few classes per namespace that are mostly used together,
but one can easily think of a lot of situations you want
to load just the classes that are really needed and in the end this is
what autoload is for)
iii. avoid the usage of autoloadb. Applications might behave differently when packaged
i. one class per file using autoload (without "use"-ing
classes from the current namespace)
ii. all classes in one filec. Implementors of autoloaders can keep the performance hit to a
minimum using some kind of caching.I think the current resolution order is a WTF-factor especially for
unexperienced users or users coming from other languages.I know that the above arguments might have been already on this list but
I couldn't find some definitive decision to keep the current name
resolution order. If I've missed that I'm sorry for the noise.Regards,
Julian Reich
Hi Jessie,
Regarding the name resolution rules, I posted a patch a few months
ago with what I think is a more reasonable lookup order (http://news.php.net/php.internals/34097
), but did not get much feedback. Would you like to try it out? (let
me know if it doesn't apply cleanly against the current PHP_5_3)
I tested the patch and it works well for me.
I think if we want a predictable name resolution without speed loss
this is the way to go.
From an "aesthetic" point of view we could even add a PHP namespace
(or even extension specific namespaces) and import all classes from
the PHP namespace into the global namespace (to avoid BC break). This
way one could use "use PHP::Exception" instead of "use ::Exception".
But I'm perfectly happy with the patch as is.
The patch didn't apply cleanly against current PHP_5_3. Therefore I
attached an adapted version.
Regards,
Julian Reich
The patch didn't apply cleanly against current PHP_5_3. Therefore I
attached an adapted version.
Sorry, attachment missing: http://www.jreich.com/php/name_resolution.patch
Regards,
Julian Reich
Julian Reich wrote:
Hi,
I recently started porting an application to PHP 5.3.
- While testing the new namespace implementation I noticed the following:
<?php
namespace Test1;
function fooBar() { echo 'Test1::fooBar()' . PHP_EOL; }namespace Test2;
use Test1;
Test1::fooBar();Executing the code above results in a warning: "The use statement with
non-compound name 'Test1' has no effect in [...]".
I understand the rationale behind this warning but it simply isn't true:
omitting the use statement results in a fatal error: "Class
'Test2::Test1' not found in [...]".Since the following code executes without warning or error I think the
code above (without use statement) should also execute just fine.<?php
namespace Test1::Test2;
function fooBar() { echo 'Test1::Test2::fooBar()' . PHP_EOL; }namespace Test3;
Test1::Test2::fooBar();
This is a clear bug, please report it at bugs.php.net
Greg
Hi,
This is a clear bug, please report it at bugs.php.net
Done: http://bugs.php.net/44653
Since "use SomeName" does the same as "use ::SomeName" dropping the
warning also be an option.
And if we split of "use" into "use namespace" and "use class" we could
resolve ambiguous calls where
a namespace and a class have the same name in a way easy to
understand. This would invalidate the
reason for the warning IMO.
Another benefit is that this way we know whether a unqualified call
should resolve to a static method or a
namespaced function and can save lookups at runtime.
Furthermore if traits were added to PHP we can simply use "use trait
TraitName". So there is no room
for confusion because of keyword reuse.
I think splitting of "use" was proposed on this list before but was
never discussed.
Regards,
Julian Reich
Hi!
Executing the code above results in a warning: "The use statement with
non-compound name 'Test1' has no effect in [...]".
This is correct, use Test1 is a no-op.
I understand the rationale behind this warning but it simply isn't true:
omitting the use statement results in a fatal error: "Class
'Test2::Test1' not found in [...]".
This seems to be a bug.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com