PHP命名空间与PSR-4自动加载

目录php

  • 命名空间
    • 概念?解决了什么问题?
    • 定义
    • 使用和解析规则
    • 其余
  • 自动加载
    • 概念?解决了什么问题?
    • PSR-4

命名空间

概念

命名空间是相似于文件系统的一个虚拟容器,能够用于类(包括抽象类和traits)、接口、函数、常量。bash

相似于文件系统,能够把类放进一个多层级的命名空间,主要是解决类名的命名冲突问题。app

定义命名空间

<?php
namespace haha\hehe\heihei
const CON1 = 10;
function run(){
 //....   
}
class ClassA{
 //....   
}

- 用namespace声明一个命名空间,代表接下去的代码属于这个命名空间
- 声明语句必须是文件第一句
- 也能够在后面加个大括号来显式代表这个命名空间范围,这样能够作到一个文件中有多个命名空间,可是很是不建议这样,不必,没有可读性,通常就是这样使用,也不用大括号


复制代码

使用命名空间

没有命名空间以前,就是ide

require('\src\ClassA.php'); 
new ClassA();
复制代码

有了命名空间后函数

//如今都配合自动加载,不require
new \haha\hehe\heihei\ClassA();
复制代码

若是屡次要new一个对象,以为累赘,能够这样ui

use haha\hehe\heihei\ClassA; //注意最前面的斜杠能够省略
$obj1 = new ClassA();
$obj2 = new ClassA();
$obj3 = new ClassA();
复制代码

这叫导入类,还能够给类起别名spa

use haha\hehe\heihei\ClassA as A; //注意最前面的斜杠能够省略
new A();
复制代码

命名解析规则

  • 解析命名空间跟文件系统的路径解析是同样的,有相对路径和绝对路径两种。
  • 绝对路径在命名空间中叫“彻底限定名”,文件系统的根目录是\,命名空间也是\,以\开头的就是彻底限定名
  • 相对路径在命名空间叫“非限定名”(只有类名),“限定名”(有路径,可是不是从\开始),总之不是\开头的
  • 绝对路径(彻底限定名)的解析没啥的,都从\开始,明明白白
  • 非彻底限定的,解析的时候就会加上当前命名空间名称
<?php
namespace My\n1amespace

new  \app\controller\User(); //彻底限定名 很清楚
new  User();                 //就解析为My\n1amespace\User
new  haha\User();            //就解析为My\n1amespace\haha\User
复制代码

其余

__NAMESPACE__常量code

<?php
namespace My\n1amespace{
    echo 'inside'.__NAMESPACE__; //My\n1amespace 若是没有命名空间就是''
}
复制代码

自动加载

概念

若是你须要用一个类,那你得先require,当你用一个类的时候,可能无所谓,当你的类用的多的时候,就很麻烦了。对象

自动加载1.0,在命名空间出现以前,就有自动加载,与原理就是,你能够告诉php解释器一个函数(用__autoload()或者spl_autoload_register()注册),当你用一个类,而又没有导入的时候,系统就会运行这个函数。接口

自动加载2.0,在命名空间出现后,PSR-4规定了一个基于命名空间的统一的自动加载规范

PSR-4

其实问题的核心是,如何从命名空间,获得实际的文件位置?

两点

  • 经过自动加载函数 将根命名空间或者较高级别的命名空间 与 目录一一关联
  • 从根目录或者特定的目录往下,命名层级与目录层级一一对应

看一个例子就知道

spl_autoload_register(function($class_name){
    //命名空间前缀
    $prefixe = '\Foo\\Bar';
    //基目录
    $base_dir = __DIR__.'/src/';
    //匹配是否 是在寻找这个命名空间下的类
    $len = strlen($prefix);
    if(strncmp($prefix,$class_name,$len)!==0){
        return ;
    }
    //将命名空间转换为目录位置
    $relative_class = substr($class.$len);
    $file = $base_dir . str_replace('\\','/',$relative_class).'.php';
    if(file)existst($file)){
        require($file);
    }
})
复制代码

参考资料


  1. php手册
  2. modern PHP 对应章节
相关文章
相关标签/搜索