Blogger Information
Blog 44
fans 0
comment 0
visits 35591
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP命名空间笔记-2019年3月6日
的博客
Original
725 people have browsed it

1. 命名空间的作用 

解决全局成员的命名冲突问题 

全局成员: 类 / 函数 / 常量 

demo1.php

<?php
// 命名空间的作用与适用对象
require 'inc/funciton.php';
function func1($a, $b)
{
    return $a.' + '.$b.' = '.($a+$b);
}
// 直接调用会出现函数未定义错误
//echo fun1(10, 20);
// 如果想访问外部加载的函数func1,就要带上命名空间
echo \my\func1(10, 20); // 做的乘法
echo '<hr>';
// 而如果还想访问在当前脚本中定义的函数func1,也要用命名空间访问
echo \func1(10,20); // 加法

inc/funciton.php

<?php
// 使用命名空间, 不改变原来的函数名称
namespace my;
function func1($a, $b)
{
    return $a.' * '.$b.' = '.($a*$b);
}


2.命名空间的定义 

namespace: 创建命名空间, 必须是脚本的第一行代码 

 在一个脚本中定义多个命名空间与成员(除全局空间) 

<?php
// 定义空间one
namespace one;
// 在one空间中定义三个全局成员
class Pig {}
function hello(){ return 'Hello 朱老师'; }
const SITE = 'php.cn';
// 访问成员
echo Pig::class . '<br>';   // 完整类名
echo hello() . '<br>';
echo SITE . '<hr>';
/*************************************************/
// 定义命名空间: two
namespace  two{
class Pig {}
function hello(){ return 'Hello 猪哥'; }
const SITE = 'php中文网';
echo Pig::class . '<br>';   // 完整类名
echo hello() . '<br>';
echo SITE . '<br>';
// 如果要在当前空间下面, 访问其它空间的成员, 例如one空间
// 与文件系统类似,从根空间开始,根空间: "\"
echo '<br>';
echo \one\Pig::class . '<br>';   // 完整类名
echo \one\hello() . '<br>';
echo \one\SITE . '<hr>';
}
// 尽管可以在一个脚本中, 可以声明多个命名空间,但并不推荐这样去做
// 使用本例的方法, 在同一个脚本中声明多个空间,但无法自定义根空间成员,只能调用
//还能使用namespaace{}命名多个命名空间


3.子命名空间 

namespace: 引用当前命名空间 

 __NAMESPACE__: 当前空间名称字符串(魔术常量) 

 one\two\three\...\ClassName: 类空间的分层管理 

<?php
// 子命名空间
// 命名空间是可以分层管理的
namespace think;
class Dog {}
echo Dog::class . '<hr>';
// 双下划线开头的魔术常量, 所谓魔术是指,尽管是常量,但可以随作用域发生变化
echo __NAMESPACE__ . '<br>';

namespace think\admin;
echo __NAMESPACE__ . '<br>';
class Dog {}
echo Dog::class . '<hr>';
// 如果我想访问空间:think\admin\model\Dog类
// 可以将当前空间看成当前目录,用关键字namespace来引用当前空间
echo namespace\model\Dog::class . '<hr>';

namespace think\admin\model;
echo __NAMESPACE__ . '<br>';
class Dog {}
echo Dog::class . '<hr>';

// "\"是命名空间分隔符, 将空间分层有什么卵用呢?
// 作用非常大, 现代PHP编程中的类的自动加载技术就靠它撑着呢,框架没有它, 难以想像
// 多层级的命名空间,非常像多层级的目录结构,如果类名称中的空间部分与类文件的绝对路径一致,就可以实现
// 类文件的全自动加载,并且不会千万命名冲突,因为类名本身仍是带有命名空间的


4.带空间的类文件自动加载技术 

str_replace(): 字符串替换函数,将空间分隔符替换成路径分隔符 

 DIRECTORY_SEPARATOR: 路径分隔符常量 

 spl_autoload_register(): 自动加载函数 

<?php
// 传统方式
//require 'inc/Class122.php';
//require 'inc/Class2.php';
//
//$obj1 = new \code\inc\Class1();
//$obj2 = new \code\inc\Class2();
//
//echo get_class($obj1) . '<br>'; //code\inc\Class1
//echo get_class($obj2) . '<br>'; //code\inc\Class2
//
//echo '<hr>';

/**********************************************************************/

// 由于类空间名称与类文件所在路径一致
// 可以通过解析类空间名称实现自动加载
// 测试
$path = str_replace('\\', '/', 'code\inc\Class1');
echo $path . '<br>';
$path = __DIR__ . '/../' . $path . '.php';
echo $path . '<br>';
echo '<hr>';
spl_autoload_register(function ($class){
    // 这里将"\"替换成路径分隔符, 推荐使用常量:DIRECTORY_SEPARATOR,而不是"/",可苑跨平台支持
    $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
    $path = __DIR__ . '/../' . $path . '.php';

    // 不是文件或文件不存在,则抛出异常
    if (!(is_file($path) && file_exists($path))) {
        throw new \Exception('不是文件或文件不存在');
    }
    require $path;
});


$obj1 = new \code\inc\Class1();
$obj2 = new \code\inc\Class2();

echo get_class($obj1) . '<br>'; //code\inc\Class1
echo get_class($obj2) . '<br>'; //code\inc\Class2


5. 空间别名 

   use namespace/className: 通过use关键字导入空间别名 

  为较长的类名提供一种简化方案 

  导入空间别名默认从全局空间开始 

  导入空间别名, 不能代替外部文件的加载 

  注意很多框架采用了自动加载技术,会导致一些同学误以为use可以加载类 

  use: 解决类名过长的问题 

  as: 解决导入的类别名与当前空间类重名问题 

<?php
// 允许通过别名引用或导入外部的完全限定名称
namespace current;
include 'inc/Class1.php';

// 如果要使用Class1类,需要先实例化
$obj = new \code\inc\Class1();
echo get_class($obj) . '<br>';
echo '<hr>';

// 你会发现,这样的类名有点长了, 实际开发过程中, 比这个长的多的是
// 如果来简化呢? 使用别名导入
//use \code\inc\Class1 AS C1;

// 现在就简单多了,其实使用use导入类别名时, 默认就是根空间(全局)开始
// 所以 "\"可以省略, 实际上也不推荐加上
//use \code\inc\Class1 AS C1;

// 如果当前脚本中没有与导入的类名冲突的类, 就没必要用AS 起一个别名了
//class Class1{},
// 此时的类的默认别名, 就是原来的名字: Class1
use code\inc\Class1;

//$obj = new C1();
$obj = new Class1();
echo get_class($obj) . '<br>';

echo '<hr>';

案例:

实例

<?php
// 命名空间实战
namespace db;

// 连接数据库: 目前在空间中写代码, PDO类中全局中, 建议加上"\"
$pdo = new \PDO('mysql:host=localhost;dbname=php','root','root');
// 如果PDO类前不加"\"也不会报错, 因为系统在当前空间中没有找到,会自动转到全局中查找, 为提升查询效率,强烈建议加上

//查询点数据展示出来,以测试数据库操作正确
$stmt = $pdo->prepare('SELECT `id`,`name`,`position` FROM `staff` LIMIT :offset, :num');
$stmt->bindValue('offset',0, \PDO::PARAM_INT);
$stmt->bindValue('num',5, \PDO::PARAM_INT);
$stmt->execute();

// 将结果集中的列绑定到变量
$stmt->bindColumn('id', $id);
$stmt->bindColumn('name', $name);
$stmt->bindColumn('position', $position);

// 遍历
while ($stmt->fetch(\PDO::FETCH_BOUND)) {
    echo "<li>{$id}.  {$name} : {$position}</li>";
}

运行实例 »

点击 "运行实例" 按钮查看在线实例


Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post