主要内容
- 全局成员
- 命名空间与对象访问
- 全局匿名空间
- 命名空间中的功能访问
- 类的加载(用spl_autoload_register的自动加载)
1. 全局成员
<?php
// 全局成员: 写在函数外部的东西
// 全局成员有四个: 函数, 常量, 类/接口
// 函数
function demo() {}
// 常量
const USER_NAME = 'Peter Zhu';
// 类
class User {}
// 接口
interface iDb {}
// 全局成员 最大的特点,全局可见
// 全局成员的最大缺点: 不能重复命名
class UserController {}
class UserCenterController {}
const USER_NAME_ROLE = 1;
2. 命名空间与对象访问
<?php
// 命名空间: 有名称的空间
// 通过目录进行内部对象访问
namespace one;
// 接口
interface iTest {
public function getSite();
}
// 类
class Demo implements iTest
{
public function getSite()
{
return 'php中文网';
}
}
// 函数
function f1(iTest $obj) {
return $obj->getSite();
}
// echo (new Demo)->getSite();
echo f1(new Demo);
//////////////////////////////////////////////
namespace two;
// 在two空间中访问one空间的类
// 使用:"\"表示全局空间,后面的类似一级一级的目录
// echo (new \one\Demo)->getSite();
// two\f1()
echo \one\f1(new \one\Demo);
// 当前语法,只能声明命名空间,而不能声明匿名空间/全局空间
- 另外一种写法
<?php
namespace one
{
class Demo
{
public function getSite()
{
return 'php中文网';
}
}
}
////////////////////
namespace two
{
echo (new \one\Demo)->getSite();
// echo '<hr>';
// // 查看当前类全名
// echo \one\Demo::class, '<br>';
// class D {}
// echo D::class;
}
3. 全局匿名空间
// 全局匿名空间
namespace
{
// 因为有了全名空间, 那么全局成员的声明就不应该放在全局,而应该放在空间中
// 全局空间应该主要写对全局对象的调用
echo (new one\Demo)->getSite();
}
4. 命名空间中的功能访问
<?php
// 在空间中访问类与访问函数有什么区别
// 同名函数的调用
namespace ns
{
// 访问类,不论是本空间的类,还是其它空间的类,都不能省略空间
echo \Test::APP, '<hr>';
function var_dump($name)
{
echo 'Hello 你调用的是我哟---' . $name;
}
/* 如果调用的函数与系统内置函数重名,则优先调用当前空间的函数
只有在当前空间找不到这个函数,再到全局中去查询
下面这种情况并没有调用系统内置的var_dump(),
而是调用了在当前空间自定义函数var_dump()
*/
var_dump(\Test::APP);
echo '<hr>';
// 必须加上全局空间标识符: \, 才可以访问到系统内置的函数
\var_dump(\Test::APP);
}
// 全局
namespace
{
class Test
{
const APP = '我的博客';
}
}
5. 命名空间及内部对象的别名
<?php
// 命名空间的别名
namespace ns1;
class T1 {}
namespace ns2;
class T1 {}
namespace ns3;
// 从当前空间开始访问另一个空间, 应该从全局开始。三类方式
// 1. 完全限定名称的类名:\ns1\T1 ,类似绝对路径
echo \ns1\T1::class, '<hr>';
// 访问ns3/sub::Hello
// \ns3\sub\Hello:完全限定名称的类名
// 类名可以省略掉与当前空间名称相当的部分
// echo \ns3\sub\Hello::class;
// 2. 限定名称的类名: sub\Hello, 理解成相对路径
echo sub\Hello::class, '<hr>';
class Work {}
// 访问当前空间中的类,不要添加空间名称
// 3. 非限定名称的类: Work
echo Work::class, '<hr>';
echo \ns2\T1::class, '<hr>';
//-----------------------------------------
// 使用空间或类名的别名来简化这种调用
// 1. 空间级的别名: 给空间起个别名,使用关键字use
// use 后面必须是一个完全限定名名称的空间或类
use \ns2 as S;
echo '别名访问: '. S\T1::class, '<hr>';
// 2. 类级的别名, 给完全限定名称的类起个别名
use \ns2\T1 as Test;
echo '别名访问: '. Test::class, '<hr>';
// 如果别名与类名相同,可以省略as以后面的别名
// use \ns2\T1 as T1;
use \ns2\T1 as TT;
echo '别名访问: '. TT::class, '<hr>';
// 以下情况必须使用别名
// 如果当前类中也有一个与之同名的非限定的类,就不能省略别名
class T1 {}
namespace ns3\sub;
class Hello {}
// 完全限定名称: 总是从全局空间开始, 前面总是一个: "\" , "\A\B..."
// 限定名称: 类名总是会有一个或多个空间名称,但不是从全局开始, "A\B..."
// 非限定名称: 就是不带有空间名称的类 " User"
6. 类的加载
<?php
// 类的加载 - 从其他文件中加载进来
require 'inc/lib/Test1.php';
require 'inc/lib/Test2.php';
require 'inc/lib/Test3.php';
use inc\lib\Test1 as T1;
use inc\lib\Test2 as T2;
use inc\lib\Test3 as T3;
echo T1::class, '<br>';
echo T2::class, '<br>';
echo T3::class, '<br>';
- 目录及文件的访问
<?php
// 目录及文件的访问
// __DIR__
// echo __DIR__, '\\demo7.php';
// require __DIR__ . '\\inc\\lib\\Test1.php';
// echo \inc\lib\Test1::class, '<br>';
// \inc\lib\Test1: 路径与空间对应
// $path = str_replace('\\', '/', '\inc\lib\Test1' );
$path = str_replace('\\', DIRECTORY_SEPARATOR, '\inc\lib\Test1' );
echo $path;
echo '<hr>';
// echo __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
require __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
// echo Test1::class, '<br>';
// 可以随操作系统不同,使用不同的目录分隔符
// echo DIRECTORY_SEPARATOR;
- 类的自动加载
- 貌似有几个很2的规定,加载的php文件名需要等于其中class的名字。
- 为了调取php中的函数,哪怕没有包括在class中,需要new下class,具体见作业部分。但其实用require的时候完全不用new class。
<?php
// 类的自动加载
try {
spl_autoload_register(function($class){
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class );
$file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
if (!(is_file($file) && file_exists($file)))
throw new \Exception('不是文件名文件不存在');
require $file;
});
} catch (Exception $e) {
die($e->getMessage());
}
use inc\lib\Test1;
use inc\lib\Test2;
use inc\lib\Test3;
echo Test1::class, '<br>';
echo Test2::class, '<br>';
echo Test3::class, '<br>';
7. 作业与实战
0729-作业
- 深刻理解三种类名称:完全限定,限定与非限定,并实例演示
- 写一个自动加载器,实现类的自动加载
选做: 想一下这个加载器能否实现函数的自动加载?
<?php
//三种方式访问空间元素
namespace liaoning\shenyang\tiexi\softpark;
const USER = "jim";
namespace beijing\haidian\xisanqi;
const USER = "root";
namespace liaoning\shenyang\tiexi;
const USER = "admin";
// ① 完全限定名称方式 访问元素 (类似 include('e:/web/0811/conf/common.php') 绝对路径引入文件)
echo \beijing\haidian\xisanqi\USER,'<br><hr>'; //root
// ② 限定名称方式 访问元素(不建议使用该方式) (类似 include('conf/common.php') 相对路径引入文件)
//该方式元素: 当前空间+访问空间+具体元素;
// liaoning\shenyang\tiexi\softpark\USER;
echo softpark\USER,'<br><hr>';
// ③ 非限定名称方式 访问元素 (类似 include('common.php') 相对路径引入文件)。同一目录下访问。
echo USER; //admin
<?php
try{
spl_autoload_register(
function($class)
{
$path = str_replace('\\',DIRECTORY_SEPARATOR,$class);
// 两个斜杠\\的意思,第一个为转意符,意思就是以\作为目录的拆分符。
$file = __DIR__.DIRECTORY_SEPARATOR.$path.'.php';
if (!(is_file($file) && file_exists($file)))
throw new \Exception('不是文件,或者文件不存在');
require $file;
}
);
}catch(Exception $e){
die($e->getMessage());
}
// 别名
use inc\lib\test1; //前面的inc\lib是命名空间。
use inc\lib\test2;
use inc\lib\test3;
echo Test1::class, '<br>';
echo Test2::class, '<br>';
echo Test3::class, '<br>';
// 引入类文件
new test1;
new test2;
new test3;
// 引入类文件中的函数
echo inc\lib\f1(),'<br>';
echo inc\lib\f2(),'<br>';
echo inc\lib\f3(),'<br>';