What's the benefit of namespaces in PHP? - php

What's the benefit of namespaces in PHP? I've worked on multiple MVC systems and haven't found much use for them. I'm reading about them here.... is it a problem of sorts that I've never used them? Is it the kind of thing that is a good coding standard to always use?

The main advantage of namespaces doesn't usually come from your own application's code, but from third party libraries. Library maintainers can select appropriate namespaces for their own code and ensure that there are no naming conflicts with your own.

Like any other languages, namespaces allow ambigious names / classes with same name to co-exists while being in two different namespaces.
For example Table class can be referring to a table in a persistent database and a HTML table. I can put namespaces to specifically use the exact table that I want, i.e. \Model\Table and \View\Table respectively.

Namespace is part of good OOP practices. They are really usefull in big web Application because they help to avoid ambiguity between classes. This is a way to organize your application and makes it more readable.

It helps you to avoid name collisions. For example, if you have two packages, and each has a class named Client (or something general like that), then it would lead to a name collision. Before PHP 5.3 the solution to avoid these collisions was to use class names like this: VendorName_PackageName_Classname
As you can see it's not too nice. But now with PHP 5.3 you can use namespaces to come up with cleaner class names.

Imagine you have a huge code base, with thousands of functions, classes and lots of third-party code. And now, two functions happen to have the same name.
That's where namespaces come in - by wrapping your code into namespaces, you can eliminate the possibility of name clashes.
Also, namespaces aid you at structuring your code - everything that belongs to a certain feature or sub-system goes into one namespace.

It also help your code more flexible and clear.
In comparing, Zend_Database_Adapter_Mysql vs Zend/Database/Adapter/Mysql is equal to avoid ambigious names.
// use namespace
use Zend/Database/Adapter/Mysql as DbAdapter;
$dbAdapter = new DbAdapter;
// use naming convention
$dbAdapter = new Zend/Database/Adapter/Mysql;
When use namespace, if adapter is changed, your code would be not modified too many. All actions are only modify 'use' command.
Note that in upon example, the factory method pattern should not be cared.

Related

Which code is better if I need to use only one static property from PHP class?

If I need to use only ::class property in my code, should I import a whole class like this?
use my\namespace\MyClass;
MyClass::class;
Or should I do this?
my\namespace\MyClass::class;
Which is a faster/better solution? Or there is no difference?
I'm using the Yii2 framework if it matters
There is no difference, it is only matter of code style. Both variants generates the same opcodes, so they work the same and there is no performance difference between them. You can use version which suits you better, but importing classes using use statement have some advantages:
It is more DRY: if you need to use the same class twice, you don't need to repeat FQN twice. It also ensures consistency - there is no risk that in one place you use my\namespace\MyClass and in other some\vendor\namespace\MyClass.
It generates less fuss on refactoring - changing class namespace will only affect import section without touching actual code that uses this class (no meaningless changes in git blame).
"import everything" is easier to follow and configure CS fixers to ensure this as CS rule.
As a result you always have a nice list of classes used in specific file, which may help you find some bugs ("uh, this should be my\namespace\MyClass instead of some\vendor\namespace\MyClass") and architectural issues ("hmm, there is 60 classes imported in this file, maybe it has too much responsibilities...").
Namespace :
Both are valid and working properly but in terms of simplicity you can declare it in one line
my\namespace\MyClass::class;

Namespace the real meaning

I have read about namespaces and I played a bit with them just now. But I want to make sure that I got this right.
1) So namespaces are here to save as from duplications of name, really good when you add sources from outside into an application for example
2) Is it a good practice to use namespaces, to avoid duplication
3) Is it a good practice to use a namespace like a folder structure, For example if I have Folder/Folder1/Fileone.php to call my namespace like this: namespace Zend/Folder1/Fileone;
I just wanted to make sure that I got this right, and namespaces are basically here to keep as organized and is good to use them know.
Exactly, namespaces make sure there's no conflict between two libraries/code bases/projects which declare the same classes. It's even useful within one application to separate different classes which may logically be given the same name; say View\User and Model\User.
You can get the same benefit by naming your classes class View_User etc., but this means you always have to use the class by that name. Look at some larger projects like Zend Framework 1.0 to see what a verbose mess this leads to. With namespaces you can use shorter names within the same namespace and alias classes to short names easily.
Yes, it's best to namespace all your code with ProjectName\... or even VendorName\ProjectName\... to make sure you're avoiding collisions with 3rd party code.
Yes, if you correlate folder names to class names (including namespaces), it's easy to use an autoloader. It also simply makes sense.

Using spl_autoload without use keyword on every page?

We have recently been rewriting our PHP application's model code using OO. We have the classes done, and we included namespacing (in the form of Project\Level1\Level2 or whatever). Since this is an already-built application, there are a lot of classes. We are using an autoloader, for ease of loading the classes, which is great. But here's where the hassle comes in.
We have probably 300 pages strewn all across the application, and all of them require a PHP file at the very beginning (a sort of bootstrap script). The autoloader script is required in that bootstrap file.
Now, most of our pages will be using at least one but likely many of the classes. We know that we have two options here:
//either call the classes using qualified names
$person = new Project\Person;
//or include the "use" keyword on every page, so we can alias the classes for ease of use
use Project\Person as Person;
$person = new Person;
But the hassle is that we would really rather not have to do this on every single page in our application:
require_once('../php/bootstrap.php');
use Project\Person\ as Person,
Project\Address\ as Address,
Project\Group\ as Group
Project\CustomField\ as CustomField;
$person = new Person;
$address = new Address;
We tried, for the heck of it, including the use keyword for all our classes in the bootstrap file, but according to the PHP manual, "Importing rules are per file basis, meaning included files will NOT inherit the parent file's importing rules."
It just seems like including these sprawling use statements on every page of our application is creating more hassle than it's worth. And what if we are using 15 classes on one page? Then the use statement would be huge.
My question is this: is it too much hassle? Are we correct in using namespaces, or is it not all that helpful in PHP? And now knowing what we are trying to do, are we doing it right? Is there something we are missing? Should we be calling classes with fully qualified names all the time or something?
(this is my first question on stackoverflow, so please let me know if I need to do anything differently or better with my questions in the future)
While using vanilla Zend Framework Autoloader might not be they way you want to go, the Zend Loader does support custom autoloaders, that can respect namespaces specified in-line or dynamically at run-time. In your case, you are using use Project\Person\ as Person which can become cumbersome, as you already noticed.
Using namespaces with the autoloader will allow you to take advantage of auto loading using simple path traversal to organize classes, without having to append large paths just to get to the interesting parts.
So, instead of new Corp_Assets_Generic_Person_Address, you could keep the folder structure and use new Namespace_Person_Address.
Namespaces avoid clashes in class names. Specially in large applications implementing autoloaders that need to load the right class from a number of different libraries. Using shorter class names makes the code easier to read but may make it harder to maintain. Adding the use statements makes it easier to read and later maintain but then it would be cumbersome to write and refactor. Documenting the expected behavior of the autoloader and using custom autoloaders to make more readable class names would be my suggestion.
In php.ini add your file as a prepend_file

PHP Namespaces: If I'm not going to need to redeclare already taken functions do I need them?

I'm wondering, that if my functions don't have similar names, do I need to use namespaces?
plus I can't get the grips of importing all namespaces from a specific folder...
I'm wondering, that if my functions don't have similar names, do I need to use namespaces?
No.
However, namespacing does offer more benefits than avoiding namespace collisions, it also forces you to maintain good directory and file structures which makes your files easy to find, and an intuitive approach to determining parent/child relationships.
For example:
// Zend/Translate/Adapter.php
class Zend_Translate/Adapter {}
// Zend/Translate/Adapter/Csv.php
class Zend_Translate_Adapter_Csv extends Zend_Translate_Adapter {}
As you can see, classes relating to similar objects are logically grouped together, and as the above code snippet demonstrates, signifies possible parent/child relationships. One caveat, even though a directory may contain a class file along with a sub-directory, it is not guaranteed that the files within the sub-directory will extend the file.
I think you are approaching this question from the wrong perspective. Sure, you can avoid using namespaces if you know you have unique function names. But that is a very short sighted approach and doesn't take into account how complex the application is, how it is structured, etc.
As mentioned by Mike, if you are going to be using frameworks like Zend or Symfony or any other code heavy on Object Orientated Programming, then I would strongly recommend using namespaces. Let's say you want to include a class from a great PHP package. Without namespaces, you will have no assurance there will not be any conflicts.
Additionally, new frameworks like Symfony 2.0 REQUIRE you to use namespaces. So you better get used to it.

Are namespaces really all that useful in frameworks?

As far as I can tell, the only reason we have namespacing in PHP is to fix the problem of classes (+ functions & constants) clashing with others classes of the same name.
The problem is that most frameworks setup their autoload and filesystem hierarchy to reflect the names of the classes. And no-one actually require()s or include()s files anymore.
So how does namespacing help this any? Either the class is loaded based off of it's name:
new Zend_Db_Table_Rowset_Abstract;
or off it's namespace
new Zend\Db\Table\Rowset\Abstract;
Either way I am stuck with only being able to create one class with this name.
/var/www/public/Zend/Db/Table/Rowset/Abstract.php
UPDATE
I'm not sure I'm getting the point across.
Even if I created two files with the same class Zend\Db\Table\Rowset\Abstract in them I still couldn't use them together since they both claim the same namespace. I would have to change their namespace names which is what we already do!
This leaves me to belive that the only use for namespaces is function names. Now we can finally have three functions all named the same thing!
Or wait, I forgot you can't do that either since each requires the namespace prefix!
a\myfunction();
b\myfunction();
c\myfunction();
Taking ircmaxell's example:
$model = new \Application\Model\User;
$controller = new \Application\Controller\User;
How is that any different than without?
$model = new Application_Model_User;
$controller = new Application_Controller_User;
This is also a neat sounding feature - but what does it truly do for us?
use \Application\Model\User as UserModel;
use \Application\Controller\User as UserController;
$foo = new UserModel;
$bar = new UserController;
Now you cannot have a class named 'UserModel' since you have a namespace setting for that term. You also still cannot have two classes named under the same alias.
I guess the good thing is that you can rename the long Zend_Db_Table_Rowset_Abstract
use Zend_Db_Table_Rowset_Abstract as RowAbstract;
leading to developer confusion about where the non-existent class "RowAbstract" is defined and coming from in the system.
My impression is that namespaces are used in a cargo cult programming fashion. Because it's new, it gets used like crazy. Deeply nested namespaces, like in Doctrine2, add no further protection against name conflicts. And it's very obvious that \nested\name\spaces are just used to achieve a 1:1 mapping to directory/file names. Clearly a code smell.
But I suppose this phenomenon is also caused by trying to mimick Java module names in PHP. And furthermore the backslash syntax doesn't convey a sensible semantic as in other languages.
Anyway, the ability to rename classes while importing namespaces is a big bon. That's useful when it actually comes to mixing conflicting definitions. And the namespace syntax can simply be added, once an actual name conflict arises. (I see no need to implement namespaces right away, when name conflicts are that rare and for most projects a purely fictional problem.)
If you do it only when required, the awkward namespace syntax never even has to rear its ugly head. If there is only one namespace level to import, you can just use namespace1\Class as LocalName and don't convolute the application with any namespace1\Class syntax. (Still it's a better idea not to use overly generic class names in namespaces.)
Actually, you can create more than one class with the same name
Suppose you have 2 classes:
\Application\Controller\User
and
\Application\Model\User
You couldn't import both into the same file without aliasing one, but you still can define both the same way:
$model = new \Application\Model\User;
$controller = new \Application\Controller\User;
Plus you can import and alias:
use \Application\Model\User as UserModel;
use \Application\Controller\User as UserController;
$foo = new UserModel;
$bar = new UserController;
So it really is quite powerful, as it does let you name your classes however you want (and reference them by arbitrary names inside your code). The only rules are reserved keywords... See: http://www.php.net/manual/en/language.namespaces.importing.php
The point you seem to be missing is that namespace names are composable. I.e. you can do:
use Zend\Db\Table as Table;
$a = new Table\Rowset();
$b = new Table\Fields();
etc. I.e. it allows you to define your context (or set of contexts) and then refer to it. Of course, you can reduce it to just one name, but you don't have to. That btw also helps with generic class names - Fields may be too generic, but Table\Fields less to.
Another thing is if you get sick of Zend tables and want to write your own Db table classes, you change the above to:
use My\Own\Table as Table;
and all the code now uses your set of classes.
Also, you don't actually define the class by the long name. What you do is:
namespace Zend\Db\Table;
class Rowset exteds AbstractRowset {
function doStuff() {
$this->fields = new Fields();
if($this->fields->areBroken()) {
throw Exception("Alas, fields are broken!");
}
}
}
Note that here we have used 4 classes from Zend\Db\Table space, but never once had to refer to them by a long name. Of course, in real life it probably won't be as easy :), but the idea is that code - especially library code - tends to be localized - i.e. if you are in Db part of the library, chances are you are using DB-related classes much more than LDAP or PDF classes. Namespacing allows you to exploit this locality by using shorter names.
You are right that namespacing doesn't help with loading - since class should be still loaded using the full name. But once you've got your loader working, you can use nice aliases instead of ugly full names - just as in the filesystem you can use nice relative paths and symlinks instead of ugly full path.
In your example Zend framework, you can throw namespace Zend; at the top of each class file, remove the Zend_ prefix from all of your classes and functions, and you (mostly) don't need to worry about name collisions ever again. Your Zend_Date class can be renamed as just Date without interfering with the built-in date classes. Meanwhile, users of your framework can write Zend\Date instead of Zend_Date which isn't any longer to type, but they now have several other options for accessing the class more easily.
It's probably not worth it to use namespaces unless you have a big project with multiple developers. I would even argue namespaces are overrated.
For example, in Java (since few people use namespaces yet in PHP I couldn't find any similar examples). These are the choices that come up for List in my IDE (Eclipse):
java.util.List
com.ibm.toad.utils.Strings.List
com.ibm.ws.objectManager.List
com.ibm.ws.webcontainer.util.List
java.awt.List
In this case, I don't really see why they couldn't have just kept java.util.List as the only List, and for example renamed java.awt.List to ScrollingList, which actually describes what it is, makes it more obvious that it is a GUI element, and avoids the collision. I would rather type out a longer and more descriptive class name than have to deal with that.
As for one of the above posters, if everyone in your team is making a class called Database perhaps you need to do some design discussion and use only one Database class instead of shoving each person's personal duplicate into a namespace.
Are you really trying to create a new class called Zend_Db_Table_Rowset_Abstract?
The more likely scenario is that you have a local class called something common like Date, Project, User, or something similar or you have a framework that already has those classes. By having namespaces, there shouldn't be any collisions.
In web2project, we've just added namespace support in v2.0 (but we don't require PHP 5.3) because our classes - like Date, DBQuery, Mail, and a few others - collided with things pretty easily. While we don't have an intention to add an external framework to the system, someone else could pretty easily if they wanted.
Are there less verbose ways of solving the problem? Potentially.. but this worked in the Java world with their piles of libraries, so it's not all new space.
Perhaps if you broaden your view a little :)
"As far as I can tell, the only reason we have namespacing in PHP is to fix the problem of classes (+ functions & constants) clashing with others classes of the same name." - yes this is a huge issue which has caused problems for many years in every language that doesn't have namespaces - everybody makes a class Database, Date, URL etc and this fixes it :)
"The problem is that most frameworks setup their autoload and filesystem hierarchy to reflect the names of the classes. And no-one actually require()s or include()s files anymore." - well actually they do, often, just because some common frameworks have had to come up with practises to work around a lack of namespaces, doesn't mean those work arounds or hacks should null and void the 'real' fix to the issue for all :)
follow?

Categories