Friday, April 8, 2011

What is a namespace and how is it implemented in PHP?

I've heard the latest PHP has support for namespaces. I know variables defined in the global scope have no namespace, so how does one make a variable in a different namespace?

Is it just a way of categorising variables/functions?

From stackoverflow
  • Namespaces are often used with libraries, the ability to reference the library code with 1 single namespace helps to not clobber up others that are already being used.

  • A namespace allows you to organize code and gives you a way to encapsulate your items.

    You can visualize namespaces as a file system uses directories to group related files.

    Basically namespaces provide you a way in which to group related classes, functions and constants.

    They also help to avoid name collisions between your PHP classes/functions/constants, and improve the code readability, avoiding extra-long class names.

    Example namespace declaration:

    <?php
    namespace MyProject;
    
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
    
    ?>
    
    alex : So for a bunch of string helper functions, I should get them out of static functions in a class and do namespace String; function match() { } etc?
  • Namespaces solve the problem of naming collisions when importing classes and functions from libraries.

    Without namespaces, if you include two libraries which happen to define a function/class with the same name (ie, two libraries that both include a class called 'user'), it will fail.

    With no namespace support in PHP, most libraries have taken to prefixing their function/class names with something that is likely to be unique, in an attempt to avoid name collisions. The trouble is, this creates longer function or class names.

    The example given here is of the exception class:

    PEAR_Form_Loader_Validate_Table_Element_Validator_Exception.
    

    You can import from a long namespace into your own local scope as an alias using the 'AS' keyword - a name you choose. Thus, you can still have a short class name of your choice in your local scope.

    The following applies an 'alias' called DbConnection to Zend::DB::Connection.

    use Zend::DB::Connection as DbConnection
    
  • Namespaces are a programming language mechanism for organizing variables, functions and classes. PHP 5.3 adds support for namespaces, which I'll demonstrate in the following example:

    Say you would like to combine two projects which use the same class name User, but have different implementations of each:

    // Code for Project One (proj1.php)
    <?php
      class User {
        protected $userId;
        public function getUserId() {
          return $this->userId;
        }
      }
      $user = new User;
      echo $user->getUserId();
    ?>
    
    // Code for Project Two (proj2.php)
    <?php
      class User {
        public $user_id;
      }
      $user = new User;
      echo $user->user_id;
    ?>
    
    <?php
      // Combine the two projects
      require 'proj1.php';
      require 'proj2.php'; // Naming collision!
      $myUser = new User; // Which class to use?
    ?>
    

    For versions of PHP less than 5.3, you would have to go through the trouble of changing the class name for all instances of the class User used by one of the projects to prevent a naming collision:

    <?php
      class ProjectOne_User {
        // ...
      }
      $user = new ProjectOne_User; // Code in Project One has to be changed too
    ?>
    

    For versions of PHP greater than or equal to 5.3, you can use namespaces when creating a project, by adding a namespace declaration:

    <?php
      // Code for Project One (proj1.php)
      namespace ProjectOne;
      class User {
        // ...
      }
      $user = new User;
    ?>
    
    <?php
      // Combine the two projects
      require 'proj1.php';
    
      use ProjectOne as One; // Declare namespace to use
    
      require 'proj2.php' // No collision!
    
      $user = new \One\User; // State which version of User class to use (using fully qualified namespace)
    
      echo $user->user_id; // Use ProjectOne implementation
    ?>
    

    For more information:

    Mohit Nanda : very well illustrated, with comments and code. +1
    invenetix : Agreed. Very well done. I just wish they went with a different delimiter between namespace and class. :(
    jakemcgraw : With the whole delimiter griping: it will work perfectly fine if you only use single quoted strings which I do for every string in php except for newlines
    jasondavis : great example and explanation, I was completely lost on what namespaces do and php.net did not help at all but your answer does, thanks +1
    Vili : Update: namespace delimiter happened to be \ instead of ::
    jakemcgraw : @Vili updated thanks

0 comments:

Post a Comment