ThinkPHP自3.2开始,源码便加入了命名空间,现在项目中用到的是3.0版本的,为了与时俱进,于是便学了下命名空间的知识,这里记录下今晚学到的很误解的地方。
eg1.
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$obj = new \namespacename\classname();
上面代码打印namespacename\classname::__construct,没有问题。
eg2
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$a = '\namespacename\classname';
$obj = new $a();
上面代码打印namespacename\classname::__construct,没有问题。
eg3
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$a = 'namespacename\classname';
$obj = new $a();
上面代码打印namespacename\classname::__construct,没有问题。
可接下来的eg4确出现问题了.
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$obj = new namespacename\classname();
上面的代码报错了'Fatal error: Class 'namespacename\namespacename\classname' not found in D:\server\www\test\1404\ff2.php on line 14',怎么使用字符串可以,为什么直接写就不行了呢???
eg5
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$obj = new classname();
上面代码打印namespacename\classname::__construct,也没有问题。
可接下来把上述这个例子变换下就出现问题了。
eg6
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$a = 'classname';
$obj = new $a();
上面的代码报错了'Fatal error: Class 'classname' not found in D:\server\www\test\1404\ff2.php on line 14',找不到类。在平时写代码过程中,为了动态调用类,也经常是用字符串这种写法,为什么会报错呢?
好吧,感觉有点绕,明天继续看看。
[续:]
刚刚看了下官方手册,给了如下的解法,__NAMESPACE__常量和namespace关键字
__NAMESPACE__用于动态创建名称,改一下eg4的代码
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$a = __NAMESPACE__ . '\classname'
$obj = new $a();
运行下就成功了。
关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素,也 即是调用时使用,仍然是改eg4的例子
namespace namespacename;
class classname {
function __construct() {
echo __METHOD__,"<br/>\n";
}
}
$obj = new namespace\classname();
运行下也
就成功了。
[续]
今天又仔细看了下官方的教程,明白了昨晚的eg4的错误,$obj = new namespacename\classname();这处代码是在当前的namespacename命名空间下,且是限定名称,在解析时是这样的namespacename\namespacename\classname(),由于脚本里没有这个类,于是解析错误便报错。而$a = 'namespacename\classname';这个可以成功,是因为这属于命名空间的动态方法范畴,“因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠是不必要的。”也就是说,类名是动态的情况下此类写法在编译时是合法的,可以找的的。同时,再看eg6的代码,官方教程中说明了,在命名空间中,使用动态语言特征,需必须使用完全限定名称(包括命名空间前缀的类名称),因此直接使用类名在编译时不成功的。