`
阿尔萨斯
  • 浏览: 4185524 次
社区版块
存档分类
最新评论

使用use语句来导入一个命名空间

 
阅读更多
PHP 5.3版特性中,重量级的特性包括 命名空间, 静态延迟绑定(late static binding) 以及 mysqlnd,当然还有其他的一些有趣的改进, 比如 __callStatic和dynamic static calls。这一节我们先来分析一下“命名空间”的细节。
PHP对命名空间的支持是一项人们期待已久的特性了。加入这一特性的主要目的是为了解决PHP中的超长类名问题。如果你准备开发一个大一点的库,那就不得 不使用比较长的类名来避免命名冲突的问题,比如下面这种怪物名字: Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive.

从5.3开始你可以使用命名空间来组织你的代码了。 不同的命名空间内可以包含相同名字的类、函数以及常量。 声明一个命名空间非常简单,只需要在文件的开始处加上namespace 语句,像下面这样

  1. <?php
  2. /** classes/my/foo/MyClass.php */
  3. namespacemy::foo;
  4. classMyClass {}//定义一个类
  5. // 当然,也可以定义函数和常量
  6. functionmyFunc() { }
  7. constMY_CONST = ‘foo’;
  8. ?>

有多种方法来访问

  1. <?php
  2. /** test.php */
  3. include(classes/my/foo/MyClass.php);
  4. // 可以随时通过完整的名称来访问一个类
  5. $foo = newmy::foo::MyClass();
  6. // 还可以使用use语句来导入一个命名空间
  7. usemy::foo;
  8. // 然后,通过foo来引用 my::foo这个命名空间
  9. $foo = newfoo::MyClass();
  10. // 也可以只导入一个类
  11. usemy::foo::MyClass;
  12. $foo = newMyClass;
  13. // 可以为命名空间或者命名空间中的类创建别名
  14. usemy::foo as MyFoo;
  15. usemy::foo::MyClass as MyFooClass;
  16. $foo = newMyFoo::MyClass();
  17. $foo = newMyFooClass();
  18. // 注意, 下面的两种写法是等价的:
  19. usemy::foo;
  20. usemy::foo as foo;
  21. // 也可以用同样的方法来访问函数和常量
  22. my::foo::myFunc();
  23. myFoo::myFunc();
  24. my::foo::MY_CONST;
  25. myFoo::MY_CONST;
  26. ?>

use语句只能导入命名空间和类,下面这种写法就不行: use my::foo::MY_CONST;。一个use语句的有效范围是从它被定义开始直到文件的结尾,你可以在全局范围内任何地方使用它。 你可以在多个文件中使用相同的命名空间。但是一个文件只应该包含一个命名空间 (这一行为可能会在最终版本中被改变,也可能用package来替换namespace关键字 :))。 尽管不能import一个函数或者常量, 但是仍然可以使用一些前缀来从命名空间中访问他们。在PHP 5.3的早期版本中,import 关键字被用来代替 use, 现在这一点已经被改变了。
“空”命名空间 (::)

如果你在函数或常量名前面使用 :: 前缀, 他们将会被从当前的引用规则中独立出来,这在命名空间中十分有用。
Life with namesapces (porting code to PHP 5.3)

如果你打算使用命名空间,那么下面几处缺陷是你应该注意的:
类的命名规则

首先,要避免在类名中使用PHP的保留字,仔细看下面的代码:

  1. <?php
  2. /** classes/my/form/element/static.php */
  3. classMyFormElementStatic {}
  4. ?>

而在使用命名空间后,代码会变成这样:

  1. <?php
  2. /** classes/my/form/element/static.php */
  3. namespacemy::form::element;
  4. classStatic {}
  5. ?>

但是因为Static 是一个保留字,所以这段代码最终会导致一个致命错误。如果你有很多类似名字的类,那么对你来说这确实是一个坏消息。
Autoloading

从5.3版本开始, __autoload()将使用类的全路径名称,这就意味着如果你已经使用了__autoload(),就要对它做一下适当的修改,举个简单的例子

  1. <?php
  2. /** test.php */
  3. function__autoload($className)
  4. {
  5. requireclasses/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;
  6. }
  7. $foo = newmy::foo::MyClass();
  8. ?>

或者选择 SPL的形式 来完成类似的功能

  1. <?php
  2. /** classes/my/core/classloader.php */
  3. namespacemy::core;
  4. functionclassLoader($className)
  5. {
  6. requireclasses/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;
  7. }
  8. spl_autoload_register(my::core::classLoader);
  9. ?>
  10. <?php
  11. /** test.php */
  12. requireclasses/my/core/classLoader.php’;
  13. $foo = newmy::foo::MyClass();
  14. ?>

get_class(), get_parent_class(), 及其他.

当你使用这类函数的时候也要注意,他们也同样返回一个类的全路径名称。

反射 API

反射 API 同样也要反映出这种新的语言特性,这部分的计划是这样的:

* 创建一个包含下面这些方法的ReflectionNamespace类: getName(), getClasses(), getFunctions(), getFiles()
* 扩展ReflectionClass 和ReflectionFunction 类并加入getNamespace() 这一新方法。

下面这些知识也是你应该了解的:

常量: __NAMESPACE__

在这一版本中我们引入了一个新的常量: __NAMESPACE__,它包含了当前引用的命名空间的名字,比如你可以使用下面的方式来实现一个SPL风格的loader

  1. <?php
  2. /** classes/my/core/classloader.php */
  3. namespacemy::core;
  4. functionclassLoader($className)
  5. {
  6. requireclasses/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;
  7. }
  8. spl_autoload_register(__NAMESPACE__.‘::classLoader);
  9. ?>

PHP对命名空间内的元素的解析流程

我不想对这部分内容作过多的解释,你可以在 PHP namespaces README 这里阅读到详细的规则(fidy注:作者对这部分的解释确实比较“简略”,建议还是读一下那个readme,其中的关键部分我会在后面贴出来)。 记住一个要点,就是PHP会首先参照当前的命名空间来解析一个元素, 让我们来看例子

  1. <?php
  2. namespacemy::foo;
  3. mysql_connect();
  4. ::mysql_connect();
  5. ?>

当你调用mysql_connect()的时候,PHP会首先到my::foo 下面去找这个函数。如果找到了就调用它,没找到的话再去调用PHP内部集成的mysql_connect()函数,而其他命名空间中定义的 mysql_connect()函数你是没办法访问到的。而使用::bar() 这种写法则可以访问到全局命名空间中的函数,它可能是PHP的内部函数,也可能是用户自定义的。

  1. <?php
  2. namespacemy::foo;
  3. core::bar();
  4. ::core::bar();
  5. ?>

在core::bar()这种情况下, PHP 会首先尝试调用my::foo::core 下面的函数bar(),如果没有找到,则尝试调用my::foo命名空间下的类core(如果存在的话)的静态方法bar(),最后尝试调用PHP的内置 类core的bar()方法。

::core::bar()这种情况下,PHP会首先尝试调用core命名空间下的 函数 bar() ,然后尝试调用全局范围内类core的静态方法bar()。

现在PHP对命名空间的支持还没有完成,很可能将来会做一些必要的改动。

补充:PHP namespaces README中的相关内容

Names inside namespace are resolved according to the following rules:1) all qualified names are translated during compilation according to

current import rules. So if we have "use A::B::C" and then "C::D::e()"

it is translated to "A::B::C::D::e()".

2) unqualified class names translated during compilation according to

current import rules. So if we have "use A::B::C" and then "new C()" it

is translated to "new A::B::C()".

3) inside namespace, calls to unqualified functions that are defined in

current namespace (and are known at the time the call is parsed) are

interpreted as calls to these namespace functions.

4) inside namespace, calls to unqualified functions that are not defined

in current namespace are resolved at run-time. The call to function foo()

inside namespace (A::B) first tries to find and call function from current

namespace A::B::foo() and if it doesn't exist PHP tries to call internal

function foo(). Note that using foo() inside namespace you can call only

internal PHP functions, however using ::foo() you are able to call any

function from the global namespace.

5) unqualified class names are resolved at run-time. E.q. "new Exception()"

first tries to use (and autoload) class from current namespace and in case

of failure uses internal PHP class. Note that using "new A" in namespace

you can only create class from this namespace or internal PHP class, however

using "new ::A" you are able to create any class from the global namespace.

6) Calls to qualified functions are resolved at run-time. Call to

A::B::foo() first tries to call function foo() from namespace A::B, then

it tries to find class A::B (__autoload() it if necessary) and call its

static method foo()

7) qualified class names are interpreted as class from corresponding

namespace. So "new A::B::C()" refers to class C from namespace A::B.

Examples

--------

<?php

namespace A;

foo(); // first tries to call "foo" defined in namespace "A"

// then calls internal function "foo"

::foo(); // calls function "foo" defined in global scope

?>

<?php

namespace A;

new B(); // first tries to create object of class "B" defined in namespace "A"

// then creates object of internal class "B"

new ::B(); // creates object of class "B" defined in global scope

?>

<?php

namespace A;

new A(); // first tries to create object of class "A" from namespace "A" (A::A)

// then creates object of internal class "A"

?>

<?php

namespace A;

B::foo(); // first tries to call function "foo" from namespace "A::B"

// then calls method "foo" of internal class "B"

::B::foo(); // first tries to call function "foo" from namespace "B"

// then calls method "foo" of class "B" from global scope

?>

The worst case if class name conflicts with namespace name

<?php

namespace A;

A::foo(); // first tries to call function "foo" from namespace "A::A"

// then tries to call method "foo" of class "A" from namespace "A"

// then tries to call function "foo" from namespace "A"

// then calls method "foo" of internal class "A"

::A::foo(); // first tries to call function "foo" from namespace "A"

// then calls method "foo" of class "A" from global scope

?>
分享到:
评论

相关推荐

    PHP命名空间namespace定义及导入use用法详解

    一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。内容空间声明后的代码便属于这个命名空间,例如: &lt;?php echo 111; //由于namespace前有代码而报错 namespace Teacher; class Person{ ...

    namespace.js:一个在 JavaScript 中创建命名空间的简单函数

    JavaScript 中的命名空间这是一个小函数,它为您在 JavaScript 中声明和使用命名空间提供了一个很好的、简单的语法。 除了处理命名空间之外,它不会做任何事情:例如,它不会尝试加载其他脚本或模块。 它遵循我的...

    vim-php-namespace:为您键入“ use”语句

    目标vim-php-namespace是一个vim插件,用于自动插入“ use”语句。产品特点导入类或函数(添加使用语句) 自动为光标下方的名称添加相应的use语句。 要使用此功能,请在~/.vimrc添加以下映射: function! ...

    PHP命名空间namespace及use的简单用法分析

    主要介绍了PHP命名空间namespace及use的简单用法,结合实例形式分析了php命名空间的功能、使用方法及相关操作注意事项,需要的朋友可以参考下

    mysql-语句大全

    1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql&gt; SHOW DATABASES; 2:2、创建一个数据库MYSQLDATA mysql&gt; CREATE DATABASE MYSQLDATA; 3:选择你所创建的数据库 mysql&gt; USE MYSQLDATA; (按回车键出现...

    学习SQL语句之SQL语句大全

     CREATE TABLE --创建一个数据库表  DROP TABLE --从数据库中删除表  ALTER TABLE --修改数据库表结构  CREATE VIEW --创建一个视图  DROP VIEW --从数据库中删除视图  CREATE INDEX --为数据库表创建一个索引...

    c#單選題精選360題

    19. 在C#中,表示一个字符串的变量应使用以下哪条语句定义?( b ) a) CString str; b) string str; c) Dim str as string d) char * str; 20、下列关于C#面向对象应用的描述中,哪项是正确的?( c )。 a) 派生类...

    PHP命名空间定义与用法实例分析

    本文实例讲述了PHP命名空间定义与用法。分享给大家供大家参考,具体如下: php的命名空间的样式跟linux的路径很...使用命名空间 MVC\Application\index.php代码 &lt;?php namespace MVC\Application; use \MVC\Model

    PHP语言开发常见问题解决办法入门总结.docx

    技巧详情:在PHP 5.3及更高版本中,利用命名空间避免类名冲突,提高代码组织性和可读性,同时结合use关键字导入所需命名空间中的类。 错误和异常处理 技巧要点:使用try-catch结构捕获和处理异常,设置适当的错误...

    MySQL查询语句大全集锦(经典珍藏).pdf

    1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql&gt; SHOW DATABASES; 2:2、创建一个数据库 MYSQLDATA mysql&gt; CREATE DATABASE MYSQLDATA; 3:选择你所创建的数据库 mysql&gt; USE MYSQLDATA; (按回车键出现 ...

    PHP命名空间namespace用法实例分析

    namespace(命名空间)相当于函数、类,划分了一个区域,这样子就使得在同个页面中可以require相同的类,使用相同名字的函数 : 在项目中比较少用 name.php: &lt;?php //命名要使用复合名称 namespace me\mine; ...

    YII框架学习笔记之命名空间、操作响应与视图操作示例

    本文实例讲述了YII框架命名空间、操作响应与视图操作。分享给大家供大家参考,具体如下: YII基础准备 1.命名空间 &lt;?php /****假设有三个同名的类,输出的值为A,B,C****/ use a\b\c\apple; use d\e\f\apple as ...

    经典SQL语句大全

    3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段 alter table tablename --添加一个自增列 add...

    PHP tp5中使用原生sql查询代码实例

    注意事项: ... 2.只要是数据库操作必须引用 use/think/... * 2 使用DB 命名空间 * */ /****************tp5中使用原生语句*******************/ //query 用于查询 其他的用execute // 插入记录 // $result = Db::e

    PHP 命名空间实例说明

    //在kkk的命名空间下使用别的命名空间,注意前面的\ use \bak\ba\ba as b;//依旧在kkk的命名空间下,但是用别名的的时候以下方法也正确 #use bak\ba\ba as b;//前面可以不使用\号 b\bab();//使用别名下命名空间的时候...

    net use使用说明

    net use使用说明,dos中很好的命令,值得使用

    如何使用net use

    net usenet usenet usenet usenet usenet usenet usenet usenet use,how to use?

    meteor-package-namespacer:流星软件包的命名空间帮助器

    这是一个软件包,可帮助您以自觉的方式管理软件包中的名称空间。 动机 这是在软件包开发中减少样板命名空间代码的一种尝试。 它将允许命名空间Meteor.Error和Meteor.methods 。 用法 假设您正在创建一个新的Foo包...

Global site tag (gtag.js) - Google Analytics