Skip to content

Instantly share code, notes, and snippets.

@jamiel
Created January 31, 2012 18:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamiel/1711933 to your computer and use it in GitHub Desktop.
Save jamiel/1711933 to your computer and use it in GitHub Desktop.
PHP 5.3 namespaces have taken away the biggest advantage of autoloading
PHP 5.3 namespaces have taken away the biggest advantage of autoloading
-----------------------------------------------------------------------
When autoloading was introduced into PHP, the PHP world rejoiced as we no
longer needed to require every class we wanted to use in our current file
at the top of our code. With the introduction of namespaces this advantage
has been completely reversed, where unless you are writing all your code in
a single namespace (unlikely) you will end up needing to "use" every class
you want to include.
To back this up, let us take the Symfony2 framework as an example as of
today (31st January 2012).
jamiel@gentoo ~/git/symfony/src $ find . -name '*.php' | wc -l
1164
So there are 1164 source files in the framework at the moment.
jamiel@gentoo ~/git/symfony/src $ egrep -r '^use ' * | wc -l
2331
There are 2331 use statements so bearing in mind symfony 1.4 has
practically *no* fluff at the top of each class, namespaces have
added an extra 2331 new age require statements.
The top 10 all have 9 of these annoying declarations!
jamiel@gentoo ~/git/symfony/src $ egrep -rc '^use ' * | sed 's/\(.*\):\([0-9]\+\)/\2:\1/' | sort -r | head -n10
9:Symfony/Component/Validator/ValidatorFactory.php
9:Symfony/Component/Security/Http/Firewall/RememberMeListener.php
9:Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
9:Symfony/Component/HttpKernel/Client.php
9:Symfony/Component/Form/Extension/Validator/Validator/DelegatingValidator.php
9:Symfony/Component/Form/Extension/Core/Type/TimeType.php
9:Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
9:Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
9:Symfony/Bundle/SecurityBundle/SecurityBundle.php
9:Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
EDIT: It would seem I am not the first to find this annoying, and this has been discussed before
by none other than Mr. Zaninotto
http://propel.posterous.com/the-end-of-autoloading
@immutef
Copy link

immutef commented Feb 1, 2012

You must not use the use statement. You can simply fallback to

$foo = new Full\Qualified\Namespace\ClassName();

instead of

use Full\Qualified\Namespace\ClassName;
// ...
$foo = new ClassName();

By the way, the use statement does not trigger an autoload.

PS: It's not there to neglect the advantage of autoloading, it's just an aliasing of your classes. So that My\Fucking\Long\Class\Name\That\I\Dont\Want\To\Type\Everytime must only be use'd once and is available in a shorter form, e.g. Everytime in this case.

@everzet
Copy link

everzet commented Feb 1, 2012

As @pminnieur said - use has nothing to do with autoloading. It just explicitly states what classes your class uses.
It's amazingly useful way to declare class dependencies and to see how deeply some service is integrated into system and whether or not you can move/rename/refactor it. Think about it as additional source documentation level.
That said, sometimes developers go insane with too deep level of namespacing, but it's only a usage problem, not a tool one.

And talking bout autoloading - PSR-0 just gives you ability to forget about class loading altogether either they are in root namespace or not.

If you're using namespaces and uses for autoloading - you're doing it wrong!

@stephaneerard
Copy link

I understand that the

use
statement is only to declare which namespaces/classes the currently defined namespace/class will use and how it will declare them in
new
statements.

But I don't understand your point about autoload'ing and then require'ing.

Use statements are not meant to trigger the autoloading, this is right. And they don't.
When the class is being instanciated, any other class being instanciated and not yet loaded will trigger the autoloading feature (include_path & spl_ registered ones).

So here you say we shouldn't rely on this behavior to load our classes.

I'm wondering how should I ?

Thank you !

@everzet
Copy link

everzet commented Feb 1, 2012

@stephaneerard use namespaces to structurize your code and use to avoid conflicts with 3rd-party code. Autoloading is a bonus, not requirement.

I'm just saying that complaints like:

use is a new require instead of autoloading

is the exact nonsense as saying:

elephant is a new helicopter instead of teleportation

@jamiel
Copy link
Author

jamiel commented Feb 1, 2012

I added a new section to the gist with some thoughts on how things can be improved (revision 728603). I still hate writing "use" statements, though.

@everzet
Copy link

everzet commented Feb 1, 2012

@jamiel

<?php
$obj = new Structure\MyClass;
$obj->helloWorld();
$obj = new Structure\MyClass2;
$obj->helloWorld();

So, seems that whole problem appeared just because you haven't RTFM? ;-)

@everzet
Copy link

everzet commented Feb 1, 2012

use doesn't import something into the current scope - it just creates alias for your namespace paths. That's it.

@jamiel
Copy link
Author

jamiel commented Feb 1, 2012

@everzet - Thanks, reverted the update seeing as that improvement exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment