命名空间

思考:在php中,函数类和常量都是不允许同名的,一旦同名就会出现冲突。但是在大型项目开发中,团队开发很难避免出现同名结构,此时就会出现同名冲突

解决的方案只能是刻意去控制不同名吗?

引入:从开发角度出发,最好的办法就是保证不同名。这样的效率和效果都是最好的,但是在大型项目中,不同团队负责的模块可能不同,那么此时就很难保证出现不同名了,

因此这个时候就需要引入一种命名空间机制来保证,即使出现了同名结构也不影响整个项目。

 

命名空间基础【掌握】

 

定义:命名空间namespace,是指认为将内存进行分割,让不同内存区域的同名结构共存,从而解决在大型项目中可能出现的重名结构问题。

1.基本语法 nameapace 空间名字

<?php


namespace my_space;           //定义一个叫做my_space的空间

2.命名空间的命名规则

  由字母、下划线和数字构成

  可以以字母和下划线开头

  较少出现多单词空间名,一个使用下划线法

3.命名空间的作用:能够创建同名结构,包含函数,常量和类

<?php


namespace my_space;           //定义一个叫做my_space的空间
function show(){
    echo __METHOD__;
}

namespace my_space2;
$name='30';
class posen{

    function show(){
        echo '同名的函数,也不报错';
    }
}

注意,在一个空间中不可以重名。

4.命名空间里面的内容

  命名空间里面可以定义同名函数、常量和类(结构),因此类结构不允许同名,这些是命名空间规范的目标(称为空间元素)

  命名空间里面可以有其他代码

<?php


namespace my_space;           //定义一个叫做my_space的空间
function show(){
    echo __METHOD__;
}

namespace my_space2;
$name='30';        //变量
echo $name;         //变量输出
class posen{         //

    public $name='杜';     //类属性
    function show(){       //类成员
        echo '同名的函数,也不报错';
    }

}

5.命名空间注意事项:命名空间的声明(第一次)必须在所有代码之前

<?php

namespace my_space;        //命名空间之前不能有任何代码
<?php

$age=666;
namespace my_space;       //错误,第一次命名空间之前不能有任何代码

注意:命名空间在一个脚本中只会定义一个(最开始),但是在讲课的时候可能会定义多个

  总结

  1.命名空间是使用namespace+空间的名称

  2.不同命名空间可以定义同名函数、常量和类(同名结构)

  3.命名空间里可以书写任意代码

  4.命名空间的定义必须在脚本的最前面

  5.一个脚本中通常只会定义一个空间

  6.命名空间其实就好比是磁盘上划分不同文件夹,用来保存同名文件

 

 

思考:命名空间既然是用来划分空间的,那么能否像文件夹层级那样?实现多层级的命名空间呢?

引入:命名空间本身就是建立一种虚拟的“围栏”,用来区分不同位置的同名结构,既然可以在内存中设置一层“围栏”,那么自然也可以设置多层,

这个就叫做子空间

 

命名空间子空间【掌握】

定义:子空间,既在已有的空间上,再在内部进行空间划分,让每个小空间独立起来

1.命名空间子空间是直接通过namespace+路径符号\ 实现

<?php


namespace my_space;     //创建一个一级空间
function display(){};

//创建一个子空间
namespace my_space\child;   //在my_space空间下创建一个子空间child
function displat(){};

2.子空间的创建不一定非要在前面创建了上级空间,即可以直接在某个脚本中创建子空间

namespace space\parent;
function display(){};

总结:

  1.子空间也是通过namespace实现,用namespace+路径\区分上下级空间名

  2.基于一个脚本中通常只有一个空间名,所以子空间的创建可以直接创建(不用一定先创建一级空间)、

  3.子空间理论上可以创建无限层级,但是实际层级根据项目需求确定(一般不超过四层)

 

 

 

 

思考:有了命名空间后,可以在同一个文件里定义不同空间,然后出现同名结构,那如何进行访问呢?

引入:其实空间就像文件夹一样,同一个文件里不能有同名文件,但是不同文件夹下肯定可以出现同名文件的,而

如果进行访问的话,就需要进入到不同的空间进行访问。

空间元素访问【掌握】

 

定义:命名空间访问,是指访问不同空间里的结构元素,如果空间里有除了函数、常量和类的其他代码,会自动执行

只有空间元素本身(函数、常量和类)是需要通过空间进行访问的,在php命名空间中,提供了三种空间元素的访问方式:

非限定名称,限定名称和完全限定名称。

1.非限定名称访问:即直接访问空间元素的名字,此类访问的是当前代码所属空间内的元素

<?php


namespace my_space;
function show(){
    echo __FUNCTION__;
}

namespace my_space3;
function show(){
    echo __FUNCTION__;
}


//访问空间元素:非限定名称(直接使用结构名字)
show();           //显示的是my_space3 show    调用show函数是在my_space3空间下

注意:非限定名称访问就好比是访问当前自己文件夹下的所有文件

2.限定名称访问,即在访问元素的前面使用相应的空间名字,非限定名称的访问时基于子空间来实现的

<?php

//定义子空间
namespace my_space\files;
function show(){
    echo __FUNCTION__;
}


//定义子空间
namespace my_space\files1;
function show(){
    echo "我是files1子空间";
}


//定义父空间
namespace my_space;
function show(){
    echo "我是父空间";
}
show();                 //父空间访问
files\show();           //子空间files 实际为当前空间my_space+files\show()

注意:限定名称访问好比访问当前文件夹下的子文件夹内容

3.完全限定名称访问,即从根鲁姆(全局)开始访问,使用\作为全局空间开始符号

<?php

//定义子空间
namespace files;
function show(){
    echo __FUNCTION__;
}


//定义子空间
namespace files1;
function show(){
    echo "我是files1子空间";
}


//定义父空间
namespace my_space;
function show(){
    echo "我是父空间";
}

//在房钱my_space空间下 使用全局限定来访问files中的show结构

\files\show();          //使用 \开始符号 全局限定   返回files show

注意:完全限定名称访问好比从磁盘根目录访问对应路径下的内容(绝对路径)

 

总结:

  1.命名空间的访问分为三种模式

  非限定名称访问:直接访问元素本身,代表当前所属空间(当前目录)

  限定名称访问:使用空间名+元素,代表访问当前空间子空间(当前目录子目录)

  完全限定名称访问:使用全局空间开始,代表从全局开始进行访问(根目录)

 

 思考:是不是有了命名空间,所有的文件都必须指定空间,如果不指定会怎么样?

引入:并非所有情况下都需要使用命名空间,命名空间时针对有些可能出现重名的内容时,才会使用的

另外,如果不使用命名空间,本质系统也认为使用了空间,这就是全局空间

 

全局空间【掌握】

定义:全局空间,即空间元素在没有定义空间的情况下所属的空间,也是所有定义的空间的顶级空间,(即所有空间都是从全局空间分离出来的)

1.没有指定空间的元素所属空间属于全局空间

<?php

function show(){
    echo __NAMESPACE__;
}

show();         //输出无   全局空间没有名字

 

2.所有空间本质都是在全局空间下划分的

<?php

namespace space;
function show(){
    echo __NAMESPACE__;
}

show();        //space空间属于从全局空间划分一部分用于space空间管理

3.全局空间元素访问,使用完全限定名称访问

<?php

function show(){
    echo __NAMESPACE__;
}

show();        //非限定名称访问:本身当前就是全局空间内,所以可以访问
\show();     //完全新丁名称访问,全局符号\+全局空间元素

4.一旦命名空间出现,那么空间元素(类,常量和函数)的访问就被限定在空间内,如果使用非限定名称访问,那么系统会以下解析(限定名称或者完全限定名称是直接按路径准确找)

  首先,一定是在自己的空间内查找

  如果找不到元素,不同空间元素的处理不同

    系统常量,系统函数如果找不到,会自动去全局空间找(也就是能找到)

    系统类是不会自动去全局空间找的(报错,提示当前所属空间元素找不到)

<?php

namespace space;
//访问空间元素  常量
echo PHP_VERSION;    //输出7.0.10  为什么能输出,我当前没有定义这个常量,它会去全局空间找

//空间元素——函数访问

echo count(array(1,2,3,4));      //返回4,现在当前空间下找,找不到去找全局空间

//访问空间类
$conn=new mysqli('localhost','root','root','senven',3306);   //报错 非限定类访问不允许
//如果想访问需要使用全局限定名称
$conn=new \mysqli('localhost','root','root','senven',3306);

5.同样的,如果一个文件有空间,包含了一个没有空间的文件,那么要访问文件中的内容,需要使用全局空间

<?php
//space01.php文件
//属于全局空间
function show(){
    echo __FILE__;
}
<?php

namespace sppace;
//包含无空间文件
include 'space01.php';
show();     //可以访问 访问是sppace空间下的show函数
<?php

namespace sppace;

include 'space01.php';
show();     //可以访问  访问space下的空间show函数
\show();   //正确,访问全局空间下的show函数
//注意:如果space空间没有show的话,直接访问show函数也是正确的,因为系统会自动寻找全局空间

总结:

  1.全局空间就是没有使用namespace定义的空间(所有空间本质都是在全局空间下划分)

  2.全局空间的元素访问使用完全限定名称访问

  3.系统内置的函数,常量和类都属于全局空间

  系统 函数,常量在空间内访问的时候系统会自动在自己空间找,如果找不到会去全局空间找

  系统类必须使用全局空间访问:\类名

 

思考:既然前面说过一个脚本中通常只会定义一个空间,那么怎么会出现这么多种访问方式呢?

引入:上述案例只是为了知识本身的规则,在实际应用中一个脚本只会有一个空间,因为一个脚本中通常只有一个类或者一些函数(功能函数)

但是因为开发的结构性,不同文档所属的功能是不同的,因此也是存放在不同的文件夹的,因此在实现业务的时候会进行文件包含,也就会产生空间包含的问题

所有就会需要多种访问方式来进行访问。

 

命名空间应用【掌握】

定义:命名空间应用是模拟真实的开发环境,来运用命名空间的规则

1.创建文件夹:模拟项目不同文件php文件放到不同文件夹下

--|root                   -------根目录

--|--|controller                ------业务模块

--|--|model                  ----数据模块

--|--|core                  ------核心工具

2.业务说明

root根目录:存放用户可以直接访问的文件,文件都是请求controller里的文件

controller目录:存放业务逻辑文件,所有业务都是类文件,业务要操作数据库,请求model里的文件,属于controller空间

model目录:存放数据库操作的类文件,一张表一个类文件,属于model空间

core目录:核心工具的存放,属于core空间

注意:层层相关,层级结构概念,首先写一个用户操作相关的,需要调用core中的数据库查询(只是个工具),在model数据模型中来想数据库操作(select* from user ),

在业务逻辑中对model中查询出来的数据进行操作。。。。。。。

3.创建3个文件:分别代表root目录里下(不需要空间),controller目录下,controller空间,model目录下的model空间

//core

core/DB_class.php

<?php

//属于核心空间
namespace core;

class DB{
    public function __construct(){
        echo '实现了数据的初始化操作<br>';
    }

    public function query($sql){
        echo '能够实现数据的查询<br>'.$sql;
    }
}

//model

model/User_class.php
<?php


//属于数据模块空间

namespace model;

//使用core下的操作数据库的类
include_once 'D:\wamp\www\root\core\DB_class.php';

class User{
    public function getAllUser(){
        $sql='select * from user';    //查询所有的访问
        // $user =new DB();            //非限定名称,在model下面找,找不到 错误
        // $user=new core\DB();        //限定名称在model下找core找db  找不大  错误
        $user=new \core\DB();
        return $user->query($sql);
    }
}

//controller

control/User_class.php
<?php


//定义空间
namespace controller;
//调用模型目录下的user类实现数据库操作:使用完全限定名称来访问

include_once 'D:\wamp\www\root\model\User_class.php';
//业务逻辑模块

//显示用户数据
class User{

    public function index(){
        //获取用户表的数据
        $user=new \model\User();
        $s=$user->getAllUser();
        echo '实现了用户的业务操作<hr>'.$s;
    }
}

//入口文件

root/index.php

<?php

//入口文件

//找到controller中对应的User_class.php
include_once 'controller/User_class.php';

$u=new controller\User();
$u->index();           //返回了数据

//实现了数据的初始化
//能够实现数据的查询
//select * from user 实现了用户的业务操作

代码说明:

  index.php在root目录下没有定义空间,内部元素属于全局空间,index.php包含了子目录controller下的User_class.php,而User类属于controller空间,所以在index.php中访问User类的时候,

可以使用限定名称(全局的i空间controller\空间元素),或者完全限定名称(\controller\空间元素)

 

  controller/User_class.php在root\controller文件夹下,定义了空间controller,所以文件里面所有访问,默认都在controller下找,controller/User类中用到了model\User类,所以需要使用完全限定名称访问

(同级别不同空间)\model\User

 

  model/User_class.php在root\model文件夹下,定义了model空间,所以文件里面所有访问,默认都在model下面找,model/User类中用到了core\DB类,所以需要使用全局限定名称访问\core\DB

 

  core\DB_calss.php在root/core文件夹下,定义了空间core

 

 

 

  总结:

  空间的实际应用是以文件为单位定义空间的

  空间的划分是按业务对应的脚本进行划分的,如业务controller,数据model等

  文件的包含和空间的包含没有联系,二者都是独立的,文件是在加载文件时,而空间在进入内存后

  空间应用,通常是采用非限定名称(自己空间里)和完全限定名称访问(其他空间)

 

 

思考:在实际应该开发中,几乎所有文件都有空间,在进行访问的时候每次都需要使用完全限定名称太麻烦了,有没有什么好的方式呢?

引入:实际开发中,一般都会进行优化,不会直接使用完全限定名称访问的,并且考虑到继承之类,会出现各种文件包含和空间交互,因此

为了能够简单的时候,可以采用空间元素引入

 

 

命名空间引入【掌握】

定义:命名空间引入其实就是将另外一个空间的元素(类,函数和常量)引入到当前空间来,当作当前空空间元素访问,从而可以减少复杂的完全限定名称访问,取而代之的是非限定名称

访问的方式

1.空间引入的方式:use关键字

<?php

namespace space1;
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
}


namespace space2;
//使用完全限定名称方式访问太过麻烦
// $obj=new \space1\man();
// $obj->show();

//使用use关键字引入空间元素
use space1\man;

$obj=new man();
$obj->show();

注意:use进行空间包含的时候,默认是从全局空间开始构建空间路径的(不是自己空间的相对路径)所以上述的代码等价于下面的代码

namespace space2;
//使用完全限定名称方式访问太过麻烦
// $obj=new \space1\man();
// $obj->show();

//使用use关键字引入空间元素
use \space1\man;

$obj=new man();
$obj->show();

2.空间引入的元素默认是类,如果要引入其他元素,就必须使用相应的关键字:function和const

<?php

namespace space1;
//空间方法
function add(){
    echo "我是空间add方法";
}
//空间常量
const SEX='女';
//空间类
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
}


namespace space2;

//引入空间元素类
use space1\man;
//引入空间元素方法
use function space1\add;
//引入空间元素常量
use const space1\SEX;

//访问space2空间中的函数

add();

//常量

echo SEX;

3.如果被引用的元素在当前空间已经存在,则会出现重名,解决方案是使用别名 as alias

<?php

namespace space1;
//空间方法
function add(){
    echo "我是空间add方法";
}
//空间常量
const SEX='女';
//空间类
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
}


namespace space2;

//此空间add
function add(){
    echo __METHOD__;
}

//由于空间space1中和space2中有同名方法 需要在引入元素的时候为方法起个别名
use function  space1\add as s;

s();
add();

注意:一旦引入的时候使用了别名,那么在使用的时候就直接通过别名使用

 

5.如果一个空间有多个元素要引入,那么可以进行一次引入多个使用逗号,分割即可

<?php

namespace space1;
//空间方法
function add(){
    echo "我是空间add方法";
}
function show(){

}
//空间常量
const SEX='女';
//空间类
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
}
class wuman{


}


namespace space2;

//一次引入多个空间元素,如class function const 必须分开写

use space1\man,space1\wuman;         //一次引用2个类

use function space1\add,space\show;  //一次引入2个函数

注意:以上方式都是在引入同一种元素,如果要引入多个不同元素,可以如下使用

<?php

namespace space1;
//空间方法
function add(){
    echo "我是空间add方法";
}
function show(){
    echo __METHOD__;
}
//空间常量
const SEX='女';
//空间类
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
};
class wuman{


}


namespace space2;

//一次引入space1的类,函数和常量
use space1\{
    man,
    function add,
    function show,
    const SEX
};     //注意这个分号是必须的,表示一行结束。

show();

6.如果说确定一个空间的所有元素都需要引入进来,也可以直接引入空间

<?php

namespace space1;
//空间方法
function add(){
    echo "我是空间add方法";
}
function show(){
    echo __METHOD__;
}
//空间常量
const SEX='女';
//空间类
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
};
class wuman{


}


namespace space2;

//引入空间
use spcace1;

注意:如果直接进行空间引入,那么被引入的空间属于当前空间的一个元素,要访问引入空间的其他元素,得从引入空间开始,即引入的空间最后一级空间名字+元素(引入空间当作当前的空间子空间)

<?php

namespace space1;
//空间方法
function add(){
    echo "我是空间add方法";
}
function show(){
    echo __METHOD__;
}
//空间常量
const SEX='女';
//空间类
class man{
    public $name="小伟";
    public function show(){
        echo $this->name;
    }
};
class wuman{


}


namespace space2;

//引入空间
use space1;
//访问被引入空间中的元素
space1\add();

总结:

  1.空间引入是解决访问时的麻烦,有完全限定名称变成非限定名称访问

  2.空间元素都可以引入,但是引入方式有区别

    类直接引入

    函数需要在use之后添加关键字function

    常量需要在use之后添加关键字const

  3.空间引入过程中如果出现重名,需要使用别名来处理,引入后在空间里可以直接访问别名

  4.可以一次性引入一个空间内的多个元素

  5.如果必须的情况下,也可以直接使用空间引入,但是注意被引入空间的元素不允许直接使用非限定名称访问  

  必须使用被引入空间的最后一级空间+元素访问(不常使用,引入方便但是使用不方便)

 

引入名称空间的类、方法、常量

    //引入命名空间的类、方法和常量
    use \China\student;
    use const China\PI;
    use function China\show;
    show();
    echo "<br>";
    echo PI;

给引入的方法 类 常量去别名

    //引入命名空间类,并且把这个类取个别名,防止类的重名
    use \China\student as stu;
    $obj= new stu();
    var_dump($obj);

 

posted @ 2020-02-21 14:17  WhiteSpace  阅读(1166)  评论(0编辑  收藏  举报