思考:在php中,函数类和常量都是不允许同名的,一旦同名就会出现冲突。但是在大型项目开发中,团队开发很难避免出现同名结构,此时就会出现同名冲突
解决的方案只能是刻意去控制不同名吗?
引入:从开发角度出发,最好的办法就是保证不同名。这样的效率和效果都是最好的,但是在大型项目中,不同团队负责的模块可能不同,那么此时就很难保证出现不同名了,
因此这个时候就需要引入一种命名空间机制来保证,即使出现了同名结构也不影响整个项目。
命名空间基础【掌握】
定义:命名空间namespace,是指认为将内存进行分割,让不同内存区域的同名结构共存,从而解决在大型项目中可能出现的重名结构问题。
1.基本语法 nameapace 空间名字
namespace my_space;//定义一个叫做my_space的空间
2.命名空间的命名规则
由字母、下划线和数字构成
可以以字母和下划线开头
较少出现多单词空间名,一个使用下划线法
3.命名空间的作用:能够创建同名结构,包含函数,常量和类
namespace my_space;//定义一个叫做my_space的空间
functionshow(){echo __METHOD__;
}
namespace my_space2;$name='30';classposen{functionshow(){echo '同名的函数,也不报错';
}
}
注意,在一个空间中不可以重名。
4.命名空间里面的内容
命名空间里面可以定义同名函数、常量和类(结构),因此类结构不允许同名,这些是命名空间规范的目标(称为空间元素)
命名空间里面可以有其他代码
namespace my_space;//定义一个叫做my_space的空间
functionshow(){echo __METHOD__;
}
namespace my_space2;$name='30'; //变量
echo $name; //变量输出
class posen{ //类
public $name='杜'; //类属性
function show(){ //类成员
echo '同名的函数,也不报错';
}
}
5.命名空间注意事项:命名空间的声明(第一次)必须在所有代码之前
namespace my_space;//命名空间之前不能有任何代码
namespace my_space;//错误,第一次命名空间之前不能有任何代码
注意:命名空间在一个脚本中只会定义一个(最开始),但是在讲课的时候可能会定义多个
总结
1.命名空间是使用namespace+空间的名称
2.不同命名空间可以定义同名函数、常量和类(同名结构)
3.命名空间里可以书写任意代码
4.命名空间的定义必须在脚本的最前面
5.一个脚本中通常只会定义一个空间
6.命名空间其实就好比是磁盘上划分不同文件夹,用来保存同名文件
思考:命名空间既然是用来划分空间的,那么能否像文件夹层级那样?实现多层级的命名空间呢?
引入:命名空间本身就是建立一种虚拟的“围栏”,用来区分不同位置的同名结构,既然可以在内存中设置一层“围栏”,那么自然也可以设置多层,
这个就叫做子空间
命名空间子空间【掌握】
定义:子空间,既在已有的空间上,再在内部进行空间划分,让每个小空间独立起来
1.命名空间子空间是直接通过namespace+路径符号\ 实现
namespace my_space;//创建一个一级空间
functiondisplay(){};//创建一个子空间
namespace my_space\child; //在my_space空间下创建一个子空间child
function displat(){};
2.子空间的创建不一定非要在前面创建了上级空间,即可以直接在某个脚本中创建子空间
namespace space\parent;function display(){};
总结:
1.子空间也是通过namespace实现,用namespace+路径\区分上下级空间名
2.基于一个脚本中通常只有一个空间名,所以子空间的创建可以直接创建(不用一定先创建一级空间)、
3.子空间理论上可以创建无限层级,但是实际层级根据项目需求确定(一般不超过四层)
思考:有了命名空间后,可以在同一个文件里定义不同空间,然后出现同名结构,那如何进行访问呢?
引入:其实空间就像文件夹一样,同一个文件里不能有同名文件,但是不同文件夹下肯定可以出现同名文件的,而
如果进行访问的话,就需要进入到不同的空间进行访问。
空间元素访问【掌握】
定义:命名空间访问,是指访问不同空间里的结构元素,如果空间里有除了函数、常量和类的其他代码,会自动执行
只有空间元素本身(函数、常量和类)是需要通过空间进行访问的,在php命名空间中,提供了三种空间元素的访问方式:
非限定名称,限定名称和完全限定名称。
1.非限定名称访问:即直接访问空间元素的名字,此类访问的是当前代码所属空间内的元素
namespace my_space;functionshow(){echo __FUNCTION__;
}
namespace my_space3;functionshow(){echo __FUNCTION__;
}
//访问空间元素:非限定名称(直接使用结构名字)
show();//显示的是my_space3 show 调用show函数是在my_space3空间下
注意:非限定名称访问就好比是访问当前自己文件夹下的所有文件
2.限定名称访问,即在访问元素的前面使用相应的空间名字,非限定名称的访问时基于子空间来实现的
namespace my_space\files;functionshow(){echo __FUNCTION__;
}//定义子空间
namespace my_space\files1;functionshow(){echo "我是files1子空间";
}//定义父空间
namespace my_space;functionshow(){echo "我是父空间";
}
show();//父空间访问
files\show(); //子空间files 实际为当前空间my_space+files\show()
注意:限定名称访问好比访问当前文件夹下的子文件夹内容
3.完全限定名称访问,即从根鲁姆(全局)开始访问,使用\作为全局空间开始符号
namespace files;functionshow(){echo __FUNCTION__;
}//定义子空间
namespace files1;functionshow(){echo "我是files1子空间";
}//定义父空间
namespace my_space;functionshow(){echo "我是父空间";
}//在房钱my_space空间下 使用全局限定来访问files中的show结构
\files\show();//使用 \开始符号 全局限定 返回files show
注意:完全限定名称访问好比从磁盘根目录访问对应路径下的内容(绝对路径)
总结:
1.命名空间的访问分为三种模式
非限定名称访问:直接访问元素本身,代表当前所属空间(当前目录)
限定名称访问:使用空间名+元素,代表访问当前空间子空间(当前目录子目录)
完全限定名称访问:使用全局空间开始,代表从全局开始进行访问(根目录)
思考:是不是有了命名空间,所有的文件都必须指定空间,如果不指定会怎么样?
引入:并非所有情况下都需要使用命名空间,命名空间时针对有些可能出现重名的内容时,才会使用的
另外,如果不使用命名空间,本质系统也认为使用了空间,这就是全局空间
全局空间【掌握】
定义:全局空间,即空间元素在没有定义空间的情况下所属的空间,也是所有定义的空间的顶级空间,(即所有空间都是从全局空间分离出来的)
1.没有指定空间的元素所属空间属于全局空间
}
show();//输出无 全局空间没有名字
2.所有空间本质都是在全局空间下划分的
namespace space;functionshow(){echo__NAMESPACE__;
}
show();//space空间属于从全局空间划分一部分用于space空间管理
3.全局空间元素访问,使用完全限定名称访问
}
show();//非限定名称访问:本身当前就是全局空间内,所以可以访问
\show(); //完全新丁名称访问,全局符号\+全局空间元素
4.一旦命名空间出现,那么空间元素(类,常量和函数)的访问就被限定在空间内,如果使用非限定名称访问,那么系统会以下解析(限定名称或者完全限定名称是直接按路径准确找)
首先,一定是在自己的空间内查找
如果找不到元素,不同空间元素的处理不同
系统常量,系统函数如果找不到,会自动去全局空间找(也就是能找到)
系统类是不会自动去全局空间找的(报错,提示当前所属空间元素找不到)
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.同样的,如果一个文件有空间,包含了一个没有空间的文件,那么要访问文件中的内容,需要使用全局空间
//属于全局空间
functionshow(){echo __FILE__;
}
namespace sppace;
//包含无空间文件include 'space01.php';
show();//可以访问 访问是sppace空间下的show函数
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
namespace core;classDB{public function__construct(){echo '实现了数据的初始化操作
';
}public function query($sql){echo '能够实现数据的查询
'.$sql;
}
}
//model
model/User_class.php
namespace model;//使用core下的操作数据库的类
include_once 'D:\wamp\www\root\core\DB_class.php';classUser{public functiongetAllUser(){$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';//业务逻辑模块
//显示用户数据
classUser{public functionindex(){//获取用户表的数据
$user=new\model\User();$s=$user->getAllUser();echo '实现了用户的业务操作
'.$s;
}
}
//入口文件
root/index.php<?php //入口文件
//找到controller中对应的User_class.php
include_once 'controller/User_class.php';$u=newcontroller\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关键字
namespace space1;classman{public $name="小伟";public functionshow(){echo $this->name;
}
}
namespace space2;//使用完全限定名称方式访问太过麻烦
// $obj=new \space1\man();
// $obj->show();
//使用use关键字引入空间元素
usespace1\man;$obj=newman();$obj->show();
注意:use进行空间包含的时候,默认是从全局空间开始构建空间路径的(不是自己空间的相对路径)所以上述的代码等价于下面的代码
namespace space2;//使用完全限定名称方式访问太过麻烦
// $obj=new \space1\man();
// $obj->show();
//使用use关键字引入空间元素
use\space1\man;$obj=newman();$obj->show();
2.空间引入的元素默认是类,如果要引入其他元素,就必须使用相应的关键字:function和const
namespace space1;//空间方法
functionadd(){echo "我是空间add方法";
}//空间常量
const SEX='女';//空间类
classman{public $name="小伟";public functionshow(){echo $this->name;
}
}
namespace space2;//引入空间元素类
usespace1\man;//引入空间元素方法
use functionspace1\add;//引入空间元素常量
use constspace1\SEX;//访问space2空间中的函数
add();//常量
echo SEX;
3.如果被引用的元素在当前空间已经存在,则会出现重名,解决方案是使用别名 as alias
namespace space1;//空间方法
functionadd(){echo "我是空间add方法";
}//空间常量
const SEX='女';//空间类
classman{public $name="小伟";public functionshow(){echo $this->name;
}
}
namespace space2;//此空间add
functionadd(){echo __METHOD__;
}//由于空间space1中和space2中有同名方法 需要在引入元素的时候为方法起个别名
use function space1\add ass;
s();
add();
注意:一旦引入的时候使用了别名,那么在使用的时候就直接通过别名使用
5.如果一个空间有多个元素要引入,那么可以进行一次引入多个使用逗号,分割即可
namespace space1;//空间方法
functionadd(){echo "我是空间add方法";
}functionshow(){
}//空间常量
const SEX='女';//空间类
classman{public $name="小伟";public functionshow(){echo $this->name;
}
}classwuman{
}
namespace space2;//一次引入多个空间元素,如class function const 必须分开写
use space1\man,space1\wuman; //一次引用2个类
use function space1\add,space\show; //一次引入2个函数
注意:以上方式都是在引入同一种元素,如果要引入多个不同元素,可以如下使用
namespace space1;//空间方法
functionadd(){echo "我是空间add方法";
}functionshow(){echo __METHOD__;
}//空间常量
const SEX='女';//空间类
classman{public $name="小伟";public functionshow(){echo $this->name;
}
};classwuman{
}
namespace space2;//一次引入space1的类,函数和常量
usespace1\{
man,
function add,
function show,
constSEX
};//注意这个分号是必须的,表示一行结束。
show();
6.如果说确定一个空间的所有元素都需要引入进来,也可以直接引入空间
namespace space1;//空间方法
functionadd(){echo "我是空间add方法";
}functionshow(){echo __METHOD__;
}//空间常量
const SEX='女';//空间类
classman{public $name="小伟";public functionshow(){echo $this->name;
}
};classwuman{
}
namespace space2;//引入空间
use spcace1;
注意:如果直接进行空间引入,那么被引入的空间属于当前空间的一个元素,要访问引入空间的其他元素,得从引入空间开始,即引入的空间最后一级空间名字+元素(引入空间当作当前的空间子空间)
namespace space1;//空间方法
functionadd(){echo "我是空间add方法";
}functionshow(){echo __METHOD__;
}//空间常量
const SEX='女';//空间类
classman{public $name="小伟";public functionshow(){echo $this->name;
}
};classwuman{
}
namespace space2;//引入空间
usespace1;//访问被引入空间中的元素
space1\add();
总结:
1.空间引入是解决访问时的麻烦,有完全限定名称变成非限定名称访问
2.空间元素都可以引入,但是引入方式有区别
类直接引入
函数需要在use之后添加关键字function
常量需要在use之后添加关键字const
3.空间引入过程中如果出现重名,需要使用别名来处理,引入后在空间里可以直接访问别名
4.可以一次性引入一个空间内的多个元素
5.如果必须的情况下,也可以直接使用空间引入,但是注意被引入空间的元素不允许直接使用非限定名称访问
必须使用被引入空间的最后一级空间+元素访问(不常使用,引入方便但是使用不方便)
引入名称空间的类、方法、常量
//引入命名空间的类、方法和常量
use\China\student;use const China\PI;use functionChina\show;
show();echo "
";echo PI;
给引入的方法 类 常量去别名
//引入命名空间类,并且把这个类取个别名,防止类的重名
use \China\student asstu;$obj= newstu();var_dump($obj);