PHP中的命名空间

取名空间

怎样是命名空间吧?

取名空间(阿拉伯语:Namespace)表示标记符(identifier)的可以知道范围。三个标记符可在八个命名空间中定义,它在区别命名空间中的含义是互不相干的。那样,在叁个新的命名空间中可定义任何标记符,它们不会与任何原来就有的标志符发生冲突,因为已部分定义都处在此外命名空间中。

简短说来定名空间是为着消除不相同库在同四个条件下利用时现身的命名冲突。举例小编要好有三个函数名为A,可是系统现本来就有叁个A函数了,那就能够并发冲突。

Composer 系列:为 PHP 配上海大学运货汽车,今后搬运不再繁缛。

取名空间

PHP中的命名空间,轻松的话就像文件夹。在同二个PHP脚本文件中不可能援引相仿名字的类仍旧函数,不过出于开垦进度中会使用第三方的SDK或然是团队合营开拓,难防止止会有命名重复的大概。

而命名空间的引进正是为着解决那风流倜傥标题,命名空间就一定于文件夹,同叁个文本夹中不能创设雷同名字的文本也许文件夹,可是只要相像名字的公文夹在差别文件中就子虚乌有此大器晚成题材。

引用豆蔻梢头段出自PHP官方文书档案的话。

怎样是命名空间?从广义上来讲,命名空间是大器晚成种包装事物的措施。在无数地方都足以见到这种抽象概念。比如,在操作系统中目录用来将相关文件分组,对于目录中的文件来讲,它就饰演了命名空间的脚色。具体譬喻,文件
foo.txt 能够同一时候在目录/home/greg 和 /home/other
中存在,但在同一个目录中不可能存在八个 foo.txt 文件。此外,在目录
/home/greg 外访谈 foo.txt
文件时,我们不得不将引得名以致目录分隔符放在文件名从前获得/home/greg/foo.txt。那一个原理应用到程序设计领域正是命名空间的定义。

在PHP中,命名空间用来解决在编排类库或应用程序时创设可选拔的代码如类或函数时遇见的两类难题:
1.
客商编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
2.
为非常短的标记符名称(常常是为着缓慢解决第风姿浪漫类主题素材而定义的卡塔尔(قطر‎创设一个小名(或简捷)的称呼,进步源代码的可读性。


取名空间定义有几点须求注意的地点


PHP中的命名空间

PHP从5.3本子初阶引进了命名空间,之后多数现成PHP类库以至框架都开首扶助它。那么PHP的命名空间怎么用吗?

logo

取名空间必得在任何具备代码在此之前扬言

命名空间必需在富有代码从前除了declare关键字


概念命名空间

下边是三个概念命名空间的例子

<?php    
//file a.php
namespace A;

const test = 'Atest'; 

function test() { 
    return __FUNCTION__; 
}

class Test{
    public function __construct(){
        return __METHOD__;
    }
}
?>

下边例子中便是四个卓绝的命名空间定义方法,唯有constfunction,class受命名空间的封锁。

简介

Composer 是 PHP
的贰个信任管理工科具。它同意你发明项目所依据的代码库,它会在您的类型中为您安装他们。

对于类库的电动加载,Composer 生成了一个 vendor/autoload.php
文件。引进那几个文件,就能够得到二个免费的自动加载帮助,这种感到真是棒极了~

正文首假诺介绍怎么样运用 Composer
自带的全自动加载机制,加载本地自定义的包(即不是源于于 packagist)。

允许将同二个命名空间的开始和结果分割寄存在分歧的文件中

也就说命名空间能够寄放在八个文件中


应用命名空间

采纳命名空间的办法如下:

<?php 
namespace B;
use A;

const test = 'Btest';
function test() { 
    return __FUNCTION__; 
}

class Test{
    public function __construct(){
        return __METHOD__;
    }
}

include "a.php";//必须包含A命名空间的文件

// 完全限定
// `Btest`从绝对位置查找输出,如果是全局函数则`test`
echo Btest;   //输出Btest

// 限定名称  
// 这里已经通过`use A`申明了在这个文件可以通过`A...`使用A命名空间的函数
echo Atest;    //输出Atest

// 非限定名称
// 非限定名称的函数`test`会从当前命名控件查找,即B
echo test;      //输出Btest

// namespace关键字代表当前命名空间
echo namespace/test;
?>

先是要在乎的是命名空间只起申明功用,也正是在应用了命名空间的时候依旧得把这么些命名空间注明的非常文件饱含进来。在选择中得以因此__NAMESPACE__来查阅当前命名空间。

更加多内容能够查阅PHP官方文书档案

使用

composer.json 文件中的 autoload 字段中增多自个儿的 autoloader

目前 Composer 扶植四种电动加载映射的法子:

  • PSR-0 autoloading
  • PSR-4 autoloading
  • classmap generation
  • files

上面只介绍
PSR-4,为啥?因为它丰盛便利好用(当你增添类时不供给重新生成
autoloader)。详细请查看 电动加载 –
参谋。

能够在同三个文本中定义多少个命名空间

能够在三个PHP脚本中定义多少个命名空间,可是这么不方便处理。同不经常间有三种概念的艺术,推荐应用第三种。

第生龙活虎种 轻易组合语法

<?php
    namespace MyProject;

        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }

    namespace AnotherProject;
        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
?>

第三种 大括号语法

<?php
    namespace MyProject {

        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
    }

    namespace AnotherProject {

        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
    }
?>

自动加载

各样文件既要表明命名控件又要手动include是十分不智能的政工,所以在和煦的PHP系统大概框架中得以应用电动加载手艺,让系统谐和去找

最简便的主意是运用函数__autoload函数,不过这一个函数只好在非命名控件下定义,相当于大局情状下:

function __autoload($class) {
  $dir = './';
  set_include_path(get_include_path().PATH_SEPARATOR.$ids_dir);
  $class = str_replace('\', '/', $class) . '.php'; 
  require_once($class); }

大器晚成旦在已经有了命名空间的类中,能够行使函数spl_autoload_register来注册一个类中的方法来代表__autoload

PSR-4(推荐)

{
    "autoload": {
        "psr-4": {
            "First\": "src/",
            "Temp\": "lib/"
        }
    }
}

地点的代码应用
PSR-4
规范,该专门的学问包涵了 PHP 最新的全自动加载标准,它必要必须运用
namespace (命名空间)的点子。

First\ 表示命名空间,必得以 \
结尾,幸免相符的命名空间以致冲突,若蕴含子命名空间,可以如此表示:First\Second\

src/ 表示命名空间所在目录为与 Composervendor 目录同级的
src 目录,如下所示:

First/
|---examples/
    |---get.php
|---src/
    |---Curl.php
|---vendor/
    |---composer/
    |---autoload.php
|---composer.json

固然急需在四个目录下搜索相同的命名前缀,能够用一个数组提供:

{
    "autoload": {
        "psr-4": {"First\": ["src/", "lib/"]}
    }
}

修改完 composer.jsonautoload 字段后须求立异一下 Composer
的自发性加载类:

composer dumpautoload -o

对应 Curl.php 的命名空间如下表示:

<?php
namespace First;

class Curl
{

}

引用 Curl.php 的措施如下:

<?php
require '../vendor/autoload.php';

use FirstCurl;

$curl = new Curl();
...
...

取名空间的几种采用方法

  1. 非限制名称 直接援引类
  2. 范围名称 援引相对路线
  3. 完全限制名称 引用相对路劲

小结

事情发生之前平素以为 namespacePHP
内置好的,只必要在某些类上宣示一下某部命名空间,在调用这几个类的地点 use
一下就好。。。

直到前几日脱离框架,单独写了多少个类,然后被 xxx class not found
错误折磨到可疑人生,才晓得供给有个 autoloader 才行。

命名空间的亮点

命名空间叁个超级重的效应,便是组件化开荒提供了福利和或者,也正是通过命名空间来组织文件,使得有个别组件的文书的路径和命名空间具有自然的关系,最后得以一直通过命名空间找到相应的文件。


题外话

现在 Composer 已经形成 PHP
的依附管理标杆,多选择这些工具为温馨的花销推动方便。

框架能大大收缩开拓开销,但一时候不便于个人本领的升高。在运用热销框架时,多看看框架的代码,不仅仅协理和煦驾驭驾驭框架,也能推动超多编程观念和本事上的增加。与君共勉
:卡塔尔


头阵于民用博客
StephenCode

同步在:

微博专栏:黑白之间

简书专项论题:曲直之间

SegmentFault
专栏:曲直之间

Wechat民众号:黒白之间

Wechat大伙儿号

Laravel框架中的自动加载

include和require关键字是透过手动的主意对相应文件实行富含,实际上PHP提供了越发有帮忙的文件满含方法,即类的机动加载方法。类的机动加载能够经过魔术变量__autoload(string
$class卡塔尔国达成,也得以经过函数spl_autoload_register注册一个活动加载相应实比如下:

<?php
function __atuoload($class){
    require_once($class.".php");
}
?>

当使用二个类名时,假诺此类未有被当下文件包括,则会调用__autoload(classState of Qatar魔术点子,而里面包车型地铁

class
为利用类的名号。但在实际上利用中,日常spl_autoload_register注册自定义函数作为活动加载类的兑现,因为__autoload(State of Qatar魔术函数只好够定义一遍,而spl_atutoload_register能够将多少个类活动加载方法注册到行列中,即创立了autoload函数队列,在调用时依照定义时的种种每一个实践。
其函数定义如下:

bool spl_autoload_register([callable class=”MathJax_Preview”> class=”MathJax” role=”textbox” aria-readonly=”true” style=””> id=”MathJax-Span-876″ class=”math”
style=”width: 12.536em; display: inline-block;”> style=”display: inline-block; position: relative; width: 10.029em; height: 0px; font-size: 125%;”> style=”position: absolute; clip: rect(1.816em 1000em 3.203em -0.424em); top: -2.717em; left: 0.003em;”> id=”MathJax-Span-877″ class=”mrow”> class=”mi” style=”font-family: MathJax_Math-italic;”>a id=”MathJax-Span-879″ class=”mi”
style=”font-family: MathJax_Math-italic;”>u id=”MathJax-Span-880″ class=”mi”
style=”font-family: MathJax_Math-italic;”>t id=”MathJax-Span-881″ class=”mi”
style=”font-family: MathJax_Math-italic;”>o id=”MathJax-Span-882″ class=”mi”
style=”font-family: MathJax_Math-italic;”>l id=”MathJax-Span-883″ class=”mi”
style=”font-family: MathJax_Math-italic;”>o id=”MathJax-Span-884″ class=”mi”
style=”font-family: MathJax_Math-italic;”>a id=”MathJax-Span-885″ class=”msubsup”> style=”display: inline-block; position: relative; width: 0.963em; height: 0px;”> style=”position: absolute; clip: rect(1.709em 1000em 2.723em -0.424em); top: -2.557em; left: 0.003em;”> id=”MathJax-Span-886″ class=”mi”
style=”font-family: MathJax_Math-italic;”>d style=”display: inline-block; overflow: hidden; height: 1px; width: 0.003em;”> style=”display: inline-block; width: 0px; height: 2.563em;”> style=”position: absolute; top: -2.291em; left: 0.536em;”> id=”MathJax-Span-887″ class=”mi”
style=”font-size: 70.7%; font-family: MathJax_Math-italic;”>f style=”display: inline-block; overflow: hidden; height: 1px; width: 0.056em;”> style=”display: inline-block; width: 0px; height: 2.456em;”> id=”MathJax-Span-888″ class=”mi”
style=”font-family: MathJax_Math-italic;”>u id=”MathJax-Span-889″ class=”mi”
style=”font-family: MathJax_Math-italic;”>n id=”MathJax-Span-890″ class=”mi”
style=”font-family: MathJax_Math-italic;”>c id=”MathJax-Span-891″ class=”mi”
style=”font-family: MathJax_Math-italic;”>t id=”MathJax-Span-892″ class=”mi”
style=”font-family: MathJax_Math-italic;”>i id=”MathJax-Span-893″ class=”mi”
style=”font-family: MathJax_Math-italic;”>o id=”MathJax-Span-894″ class=”mi”
style=”font-family: MathJax_Math-italic;”>n id=”MathJax-Span-895″ class=”mo”
style=”font-family: MathJax_Main;”>[ id=”MathJax-Span-896″ class=”mo”
style=”font-family: MathJax_Main;”>, class=”mi”
style=”font-family: MathJax_Math-italic; padding-left: 0.163em;”>b id=”MathJax-Span-898″ class=”mi”
style=”font-family: MathJax_Math-italic;”>o id=”MathJax-Span-899″ class=”mi”
style=”font-family: MathJax_Math-italic;”>o id=”MathJax-Span-900″ class=”mi”
style=”font-family: MathJax_Math-italic;”>l style=”display: inline-block; width: 0px; height: 2.723em;”> style=”border-left: 0.003em solid; display: inline-block; overflow: hidden; width: 0px; height: 1.47em; vertical-align: -0.463em;”>

throw=true[,bool $prepend=false]]])

通过spl_autoload_register(卡塔尔国函数加载的自行加载函数能够是大局函数,也能够是有个别类实例对象的函数,即因此array(“对象名”,“函数名”State of Qatar注册。


laravle中的达成情势

在laravel框架中,通过函数spl_autoload_register()兑现类的自动加载函数的登记,个中类的机动加载函数队列中含有了三个类的电动加载函数,三个是composer生成的基于PSXC60规范的机关加载函数,另多个是Laravel框架核心别称的活动加载函数。
中间composer生成的自动加载函数注册进程如下:

文件 laravelpublicindex.php

<?php
    require __DIR__.'/../bootstrap/autoload.php';
?>

文件 laravelbootstrapautoload.php

<?php
    define('LARAVEL_STATR',micotime(true));
    requier __DIR__.'/../vendor/autoload.php';
?>

在Laravel框架中,publicindex.php文件作为文件的入口,个中第一句就爱保护鸟类了全自动加载文件autoload.php,那一个文件中三番若干次蕴含坐落于vendor目录下的composer的机动加载文件。

文件 laravelvendorautoload.php

<?php
    require_once __DIR__ . '/composer' . '/autoload_real.php';
    return ComposerAutoloaderInit9f6ff2d01ba6cb93f0cabaf91359a37c::getLoader();
?>

透过composer工具创制正视管理时,会在vendor目录下创办autoload.php文件和二个composer文件夹,当中composer
文件夹中带有了类活动加载函数注册的相干贯彻,而autoload.php文件时对外提供接口,通过包含该公文就足以做到类活动加载函数的登记。通过上述代码能够观察,autoload.php文件满含了composer目录下的autoload_real.php文件,而autoload_real.php文件中定义了一个类,这么些类末尾有风姿洒脱串数字的法子定义,并且定义了getLoader(卡塔尔函数,该函数首先实例化ComposerAutoloadClassLoader类,然后通过该实例增加相关的文件路线配置,饱含取名空间(autoload_namespaces.php文件定义卡塔尔国配置,PSENCORE-4标准(autoload_psr4.php文件定义卡塔尔配置,类映射(autoload_classmap.php文件定义卡塔尔配置,接着调用$loader->register(true)注册类自动加载函数,最后加载全局文件,即在autoload_files.php文本中布署的内容。

上面介绍怎么着注册类自动加载函数,以至类活动加载函数时怎么完结类活动加载的。

文件:laravelvendercomposerClassLoader.php

<?php
namespace ComposerAutoload;
class ClassLoader{
    //省略加载文件路径函数的相关代码
    public function register($prepend = false){
        spl_autoload_register(array($this,'loadClass'),true,$prepend);
    }

    public function loadClass($class){
        if($file = $this->findFile($class)) {
            includeFile($file);
            return true;
        }
    }
}
//省略了根据加载文件路劲查找文件具体位置的相关代码
?>

透过前边的牵线,已经明白了类的自发性加载时在ComposerAutoloadClassLoader类中达成的,实例化该类并将此类的命名空间和文件路线的附和关系注册到对应的性质中,然后通超过实际例方法register($prepend

false卡塔尔国注册三个类活动加载函数,即为该类实例的loadClass方法,并且将其登记在类活动加载函数系列的终极,当使用贰个未富含的类名时,会活动调用loadClass方法并通过参数获取包蕴命名空间的类名消息,接着依照类的命名空间与公事路线的呼应关系查找文件路线,最终经过includeFile(卡塔尔函数包括该公文,达成类的活动加载。

默许Laravel框架饱含多个类的机动加载函数,个中一个时在外观注册(IlluminateFoundationBootstrapRegisterFacades类达成的卡塔尔国进度中落实的,这里只须要领悟犹如此一个类活动加载函数被注册到库房中就足以,后边能够在“须要到相应的生命周期”内容,精通调用过程,这里只介绍类的机关加载函数的登记进程。在登记进度中也是有先实例化后调用的register(卡塔尔国函数,进而调用prependToLoaderStack(State of Qatar函数,将load($alias)函数注册未类的机关加载函数,该函数的职能首要时将外观别称与外观名(FacadesState of Qatar对应起来,从而达成对应外观类的静态方法调用。对应类的全自动加载函数注册进程实现代码如下:

文件 IlluminateFoundationAliasLoader.php

<?php
namespace IlluminateFoundation;
class AliasLoader {
    //加载一个类别名,实际上是给外观类起了一个别名,使两个对应一个类
    public function load($alias){
        if(isset($this->alliases($alias))){
            return class_alias($this->aliases[$alias],$alias);
        }
    }
    //添加别名到自动加载函数中
    public fucntion alias($class, $alias) {
        $this->aliases[$class] = $alias;
    }

    //注册自动加载函数到自动加载堆栈中
    public function register (){
        if(!$this->registered) {
            $this->prependToLoaderStack();
            $this->registered = true;
        }
    }

    //将类的自动加载函数添加在自动加载堆栈首部
    protected function prependToLoaderStack(){
        spl_autoload_register([$this,'load'],true,true);
    }

}

?>

发表评论

电子邮件地址不会被公开。 必填项已用*标注