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

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

PHP 5.3版本将会在2008年的早些时候发布, 现在我想应该是时候谈一谈这个版本的新特性了。在这些特性中,重量级的特性包括 命名空间, 静态延迟绑定(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. namespace my::foo;
  4. class MyClass {}//定义一个类
  5. // 当然,也可以定义函数和常量
  6. function myFunc() { }
  7. const MY_CONST = ‘foo’;
  8. ?>

有多种方法来访问

  1. <?php
  2. /** test.php */
  3. include(‘classes/my/foo/MyClass.php’);
  4. // 可以随时通过完整的名称来访问一个类
  5. $foo = new my::foo::MyClass();
  6. // 还可以使用use语句来导入一个命名空间
  7. use my::foo;
  8. // 然后,通过foo来引用 my::foo这个命名空间
  9. $foo = new foo::MyClass();
  10. // 也可以只导入一个类
  11. use my::foo::MyClass;
  12. $foo = new MyClass;
  13. // 可以为命名空间或者命名空间中的类创建别名
  14. use my::foo as MyFoo;
  15. use my::foo::MyClass as MyFooClass;
  16. $foo = new MyFoo::MyClass();
  17. $foo = new MyFooClass();
  18. // 注意, 下面的两种写法是等价的:
  19. use my::foo;
  20. use my::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. class MyFormElementStatic {}
  4. ?>

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

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

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

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

  1. <?php
  2. /** test.php */
  3. function __autoload($className)
  4. {
  5. require ‘classes/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;
  6. }
  7. $foo = new my::foo::MyClass();
  8. ?>

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

  1. <?php
  2. /** classes/my/core/classloader.php */
  3. namespace my::core;
  4. function classLoader($className)
  5. {
  6. require ‘classes/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;
  7. }
  8. spl_autoload_register(‘my::core::classLoader’);
  9. ?>
  10. <?php
  11. /** test.php */
  12. require ‘classes/my/core/classLoader.php’;
  13. $foo = new my::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. namespace my::core;
  4. function classLoader($className)
  5. {
  6. require ‘classes/’.str_replace(‘::’, DIRECTORY_SEPARATOR, $className).‘.php’;
  7. }
  8. spl_autoload_register(__NAMESPACE__.‘::classLoader’);
  9. ?>

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


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

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


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

  1. <?php
  2. namespace my::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

?>
时间: 2024-10-28 14:26:41

PHP 使用use语句来导入一个命名空间的相关文章

Python将JSON格式数据转换为SQL语句以便导入MySQL数据库

前文中我们把网络爬虫爬取的数据保存为JSON格式,但为了能够更方便地处理数据,我们希望把这些数据导入到MySQL数据库中.phpMyadmin可以把MySQL数据库中的数据导出为JSON格式文件,但却不能把JSON格式文件导入到MySQL数据库.为了实现这个目标,可以编写Python脚本将JSON格式数据转换为SQL语句以便导入MySQL数据库. JSON文件tencent.json部分内容: {"recruitNumber": "1", "name&qu

SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比

原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了.我从简单到复杂地写,希望高手们不要见笑.下面的sql语句设计到三个表,表的内容我用txt文件复制进去,这里不妨使用上一个随笔介绍的建立端到端的package的方法将这些表导入到数据库中,具体的就不说了. 从这里下载文件employ

IDEA导入一个新项目原来没有问题,出现非法字符正解

新导入一个项目,项目代码没有女人和问题 ,在Eclipse上面都能跑的起来,然后导入到IDEA中就不行了 ,出现非法字符 原来就遇到过这样的问题,解决了,没注意过一段时间有忘记了,今天下下啦,给大家提个醒,程序员真到要经常写博客 下面看下出现的问题的截图 原因是没有设置编码格式,到setting里面找到file encoding ,设置一下编码格式 好了,设置完毕后再次运行就没问你啦

导入一个AndroidStudio工程作为一个Library Module

尊重劳动成果,转载请注明出处:http://blog.csdn.net/growth58/article/details/47441245 关注新浪微博:@于卫国 邮箱:[email protected] 在我们有两个Android Studio工程的情况时,我们想使用一个作为library工程导入到另一个工程作为一个module.我们可以使用Android Studio很容易的做到. 让我们假设我们有两个工程:MyApplication和MyLibrary,我们想导入MyLibrary到MyA

1.Maven+SpringMVC+Eclipse软件安装配置,Maven报插件错误,Eclipse总是卡死的解决办法,导入一个maven工程后 一直显示importing maven project

 使用Maven+SpringMVC+Eclipse软件安装配置过程中的问题: 1.Eclipse总是卡死的解决办法: 一:内存不足所以会卡死,配置一下eclipse.ini修改这几个值就好了-XX:MaxPermSize=768m-Xms1024m-Xmx3072m搜索 二:修改window->preferences --- > JAVA->Edittor->Hovers,将右侧所有复选框清空. 2.因为eclipse上一次未正常关闭,导致启动卡死,错误日志为: [plain

sql语句备份/导入 mysql数据库或表命令

sql语句备份/导入 mysql数据库或表命令,布布扣,bubuko.com

action中redirectAction到另一个命名空间中的action该如何配置

action中redirectAction到另一个命名空间中的action该如何配置,请注意namespace这儿必须是/global,而不是global,要不然找不到此action的

plsql导入一个文件夹下所有excel

import java.io.File; import java.util.ArrayList; import jxl.Sheet; import jxl.Workbook; import com.jielan.util.DBUtil; import com.jielan.util.Oracle; public class Test { private ArrayList<String> filelist = new ArrayList<String>(); public stat

在Intellij上面导入一个项目

为了学习这篇文章里面下载的代码:http://www.cnblogs.com/charlesblc/p/6083687.html 需要用Intellij导入一个已有工程.源文件原始内容也可见:link 选择 Import Project -> "Create Project from existing sources" ->选择root目录,一步步选择完毕. 为了从百度maven服务器更快的下载,在pom.xml最下面加上以下repo地址: <repositories