命名空间
在线手册:中文  英文

命名空间和动态语言特征

PHP 命名空间的实现受到其语言自身的动态特征的影响。因此,如果要将下面的代码转换到命名空间中:

Example #1 动态访问元素

example1.php:

<?php
class classname
{
    function 
__construct()
    {
        echo 
__METHOD__,"\n";
    }
}
function 
funcname()
{
    echo 
__FUNCTION__,"\n";
}
const 
constname "global";

$a 'classname';
$obj = new $a// prints classname::__construct
$b 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"// prints global
?>
必须使用完全限定名称(包括命名空间前缀的类名称)。注意因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠是不必要的。

Example #2 动态访问命名空间的元素

<?php
namespace namespacename;
class 
classname
{
    function 
__construct()
    {
        echo 
__METHOD__,"\n";
    }
}
function 
funcname()
{
    echo 
__FUNCTION__,"\n";
}
const 
constname "namespaced";

include 
'example1.php';

$a 'classname';
$obj = new $a// prints classname::__construct
$b 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"// prints global

/* note that if using double quotes, "\\namespacename\\classname" must be used */
$a '\namespacename\classname';
$obj = new $a// prints namespacename\classname::__construct
$a 'namespacename\classname';
$obj = new $a// also prints namespacename\classname::__construct
$b 'namespacename\funcname';
$b(); // prints namespacename\funcname
$b '\namespacename\funcname';
$b(); // also prints namespacename\funcname
echo constant('\namespacename\constname'), "\n"// prints namespaced
echo constant('namespacename\constname'), "\n"// also prints namespaced
?>

请一定别忘了阅读 对字符串中的命名空间名称转义的注解.


命名空间
在线手册:中文  英文

用户评论:

Alexander Kirk (2011-07-06 00:57:08)

When extending a class from another namespace that should instantiate a class from within the current namespace, you need to pass on the namespace.

<?php // File1.php
namespace foo;
class 
{
    public function 
factory() {
        return new 
C;
    }
}
class 
{
    public function 
tell() {
        echo 
"foo";
    }
}
?>

<?php // File2.php
namespace bar;
class 
extends \foo\{}
class 
{
    public function 
tell() {
        echo 
"bar";
    }
}
?>

<?php
include "File1.php";
include 
"File2.php";
$b = new bar\B;
$c $b->factory();
$c->tell(); // "foo" but you want "bar"
?>

You need to do it like this:

When extending a class from another namespace that should instantiate a class from within the current namespace, you need to pass on the namespace.

<?php // File1.php
namespace foo;
class 
{
    protected 
$namespace __NAMESPACE__;
    public function 
factory() {
        
$c $this->namespace '\C';
        return new 
$c;
    }
}
class 
{
    public function 
tell() {
        echo 
"foo";
    }
}
?>

<?php // File2.php
namespace bar;
class 
extends \foo\{
    protected 
$namespace __NAMESPACE__;
}
class 
{
    public function 
tell() {
        echo 
"bar";
    }
}
?>

<?php
include "File1.php";
include 
"File2.php";
$b = new bar\B;
$c $b->factory();
$c->tell(); // "bar"
?>

(it seems that the namespace-backslashes are stripped from the source code in the preview, maybe it works in the main view. If not: fooA was written as \foo\A and barB as bar\B)

scott at intothewild dot ca (2009-08-07 15:33:34)

as noted by guilhermeblanco at php dot net, 

<?php

  
// fact.php

  
namespace foo;

  class 
fact {

    public function 
create($class) {
      return new 
$class();
    }
  }

?>

<?php 

  
// bar.php

  
namespace foo;

  class 
bar {
  ... 
  }

?>

<?php

  
// index.php
 
  
namespace foo;

  include(
'fact.php');
  
  
$foofact = new fact();
  
$bar $foofact->create('bar'); // attempts to create \bar
                                  // even though foofact and
                                  // bar reside in \foo

?>

guilhermeblanco at php dot net (2009-06-16 12:04:00)

Please be aware of FQCN (Full Qualified Class Name) point.
Many people will have troubles with this:

<?php

// File1.php
namespace foo;

class 
Bar { ... }

function 
factory($class) {
    return new 
$class;
}

// File2.php
$bar = \foo\factory('Bar'); // Will try to instantiate \Bar, not \foo\Bar

?>

To fix that, and also incorporate a 2 step namespace resolution, you can check for \ as first char of $class, and if not present, build manually the FQCN:

<?php

// File1.php
namespace foo;

function 
factory($class) {
    if (
$class[0] != '\\') {
        echo 
'->';
         
$class '\\' __NAMESPACE__ '\\' $class;
    }

    return new 
$class();
}

// File2.php
$bar = \foo\factory('Bar'); // Will correctly instantiate \foo\Bar

$bar2 = \foo\factory('\anotherfoo\Bar'); // Wil correctly instantiate \anotherfoo\Bar

?>

易百教程