PHP类的自动加载和命名空间

简介:

浅析PHP类的自动加载和命名空间

php是使用require(require_once)和include(include_once)关键字加载类文件。但是在实际的开发工程中我们基本上不会去使用这些关键字去加载类。 因为这样做会使得代码的维护相当的困难。实际的开发中我们会在文件的开始位置用use关键字使用类,然后直接new这个类就可以了. 至于类是怎么加载的,一般都是框架或者composer去实现的。

<?php

use IlluminateContainerContainer;

$container = new Container();
自动加载
我们可以通过一段伪代码来模拟一下在类的实例化工程中类是如何工作的

function instance($class)
{

// 如果类已加载则返回其实例
if (class_exists($class, false)) {
    return new $class();
}
// 查看 autoload 函数是否被用户定义
if (function_exists('__autoload')) {
    __autoload($class); // 最后一次加载类的机会
}
// 再次检查类是否存在
if (class_exists($class, false)) {
    return new $class();
} else { // 系统:我实在没辙了
    throw new Exception('Class Not Found');
}

}
php在语言层面提供了__autoload 魔术方法给用户来实现自己的自动加载逻辑。当用户去new一个类的时候,如果该类没有被加载,php会在抛出错误前调用__autoload方法去加载类。下面的例子中的__autoload方法只是简单的输出要加载类的名称, 并没有去实际的加载对应的类, 所以会抛出错误。

<?php

use IlluminateContainerContainer;

$container = new Container();

function __autoload($class)
{

/* 具体处理逻辑 */
echo $class;// 简单的输出要加载类的名称

}

/**
*
运行结果
IlluminateContainerContainer
Fatal error: Uncaught Error: Class 'IlluminateContainerContainer' not found in D:projectphplaravel_for_ci_cdtestClassLoader.php:5
Stack trace:

0 {main}

thrown in D:projectphplaravel_for_ci_cdtestClassLoader.php on line 5
*/
明白了 __autoload 函数的工作原理之后,我们来用它去实现一个最简单自动加载。我们会有index.php和Person.php两个文件在同一个目录下。

//index.php
<?php
function __autoload($class)
{

// 根据类名确定文件名
$file = './'.$class . '.php';
if (file_exists($file)) {
    include $file; // 引入PHP文件
}

}
new Person();

/---------------------分割线-------------------------------------/

//Person.php
class Person
{

// 对象实例化时输出当前类名
function __construct()
{
    echo '<h1>' . __CLASS__ . '</h1>';
}

}

/**运行结果

  • 输出

    Person


    */

命名空间
命名空间并不是什么新鲜的事务,很多语言都早就支持了这个特性(只是叫法不相同),它主要解决的一个问题就是命名冲突! 就好像日常生活中很多人都会重名,我们必须要通过一些标识来区分他们的不同。比如说现在我们要用php介绍一个叫张三的人 ,他在财务部门工作。我们可以这样描述。

namespace 财务部门;

class 张三
{

function __construct()
{
    echo '财务部门的张三';
}

}
这就是张三的基本资料 , namespace是他的部门标识,class是他的名称. 这样大家就可以知道他是财务部门的张三而不是工程部门的张三。

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

1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment(); 如果当前命名空间是BlogArticle,Comment将被解析为、BlogArticleComment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

注意: 如果文件的开头有使用use关键字 use onetwoComment; 则Comment会被解析为 onetwoComment

2.限定名称,或包含前缀的名称,例如 $comment = new ArticleComment(); 如果当前的命名空间是Blog,则Comment会被解析为BlogArticleComment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为ArticleComment。

3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new ArticleComment(); 在这种情况下,Comment总是被解析为ArticleComment。

spl_autoload

接下来让我们要在含有命名空间的情况下去实现类的自动加载。我们使用 spl_autoload_register() 函数来实现,这需要你的 PHP 版本号大于 5.12。spl_autoload_register函数的功能就是把传入的函数(参数可以为回调函数或函数名称形式)注册到 SPL __autoload 函数队列中,并移除系统默认的 __autoload() 函数。一旦调用 spl_autoload_register() 函数,当调用未定义类时,系统就会按顺序调用注册到 spl_autoload_register() 函数的所有函数,而不是自动调用 __autoload() 函数。

现在, 我们来创建一个 Linux 类,它使用 os 作为它的命名空间(建议文件名与类名保持一致):

<?php
namespace os; // 命名空间

class Linux // 类名
{

function __construct()
{
    echo '<h1>' . __CLASS__ . '</h1>';
}

}
接着,在同一个目录下新建一个 index.php文件,使用 spl_autoload_register 以函数回调的方式实现自动加载:

<?php

spl_autoload_register(function ($class) { // class = osLinux

/* 限定类名路径映射 */
$class_map = array(
    // 限定类名 => 文件路径
    'os\\Linux' => './Linux.php',
);
/* 根据类名确定文件路径 */
$file = $class_map[$class];
/* 引入相关文件 */
if (file_exists($file)) {
    include $file;
}

});

new osLinux();
这里我们使用了一个数组去保存类名与文件路径的关系,这样当类名传入时,自动加载器就知道该引入哪个文件去加载这个类了。但是一旦文件多起来的话,映射数组会变得很长,这样的话维护起来会相当麻烦。如果命名能遵守统一的约定,就可以让自动加载器自动解析判断类文件所在的路径。接下来要介绍的PSR-4 就是一种被广泛采用的约定方式

PSR-4规范

PSR-4 是关于由文件路径自动载入对应类的相关规范,规范规定了一个完全限定类名需要具有以下结构:

<顶级命名空间>(<子命名空间>)*<类名>

PSR-4 规范中必须要有一个顶级命名空间,它的意义在于表示某一个特殊的目录(文件基目录)。子命名空间代表的是类文件相对于文件基目录的这一段路径(相对路径),类名则与文件名保持一致(注意大小写的区别)。

举个例子:在全限定类名 appviewnewsIndex 中,如果 app 代表 C:Baidu,那么这个类的路径则是 C:BaiduviewnewsIndex.php.我们就以解析 appviewnewsIndex 为例,编写一个简单的 Demo:

<?php

$class = 'appviewnewsIndex';

/ 顶级命名空间路径映射 /
$vendor_map = array(

'app' => 'C:\Baidu',

);

/ 解析类名为文件路径 /
$vendor = substr($class, 0, strpos($class, '\')); // 取出顶级命名空间[app]
$vendor_dir = $vendor_map[$vendor]; // 文件基目录[C:Baidu]
$rel_path = dirname(substr($class, strlen($vendor))); // 相对路径[/view/news]
$file_name = basename($class) . '.php'; // 文件名[Index.php]

/ 输出文件所在路径 /
echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;
原文地址https://www.cnblogs.com/php-learning-road/p/12196077.html

相关文章
|
15天前
|
PHP 项目管理 开发者
深入解析PHP的命名空间和自动加载机制
【4月更文挑战第4天】 在PHP的编程世界中,命名空间和自动加载机制是构建大型应用程序时不可或缺的工具。本文将深入探讨这两个概念,揭示它们如何简化代码结构、避免类名冲突以及提高代码维护性。通过对PHP命名空间的由来、作用域和使用方法的细致剖析,以及对自动加载机制工作原理和应用实践的全面讲解,读者将获得有效管理复杂项目中依赖关系的能力。
|
17天前
|
缓存 PHP 开发者
PHP中的自动加载机制及其优化方法
传统的PHP开发中,经常会遇到类文件加载繁琐、效率低下的情况,而PHP的自动加载机制能够很好地解决这一问题。本文将深入探讨PHP中的自动加载机制,介绍其原理及实现方式,并提出了一些优化方法,帮助开发者提升代码加载效率,提高应用性能。
|
21天前
|
PHP 数据库 开发者
深入理解PHP中的命名空间与自动加载机制
在PHP开发实践中,合理利用命名空间和自动加载机制能够显著提升代码的可维护性和效率。本文将详细探讨PHP命名空间的概念、作用以及如何结合自动加载机制来优化代码结构。通过实例分析,我们将了解如何避免常见的命名冲突问题,并掌握自动加载策略在项目中的实际应用。文章的目的是为读者提供一套清晰的指南,帮助其在实际项目中灵活运用这些关键技术,以实现更加模块化和高效的代码管理。
|
30天前
|
PHP 开发者
深入理解PHP的命名空间与自动加载机制
【2月更文挑战第29天】在现代PHP开发实践中,命名空间和自动加载机制是提升代码组织和维护效率的重要概念。本文首先介绍命名空间的基本概念及其在PHP中的应用,然后详细探讨了自动加载机制的原理与实现,并通过示例展示了如何在实际项目中合理运用这些特性来优化代码结构,减少冗余,并提高模块间的解耦性。
|
24天前
|
PHP
深入理解PHP的命名空间与自动加载机制
在现代PHP开发中,命名空间和自动加载机制是两个重要的特性,它们有助于解决代码重用、依赖管理等问题。本文将详细介绍PHP的命名空间概念、如何定义和使用命名空间,以及自动加载机制的原理和实现方法。通过阅读本文,你将更好地理解这些特性,并能够在实际项目中灵活运用。
|
1月前
|
PHP
深入理解PHP的命名空间和自动加载机制
【2月更文挑战第21天】在PHP开发中,命名空间和自动加载机制是两个非常重要的概念。本文将深入探讨这两个概念,解释它们的作用,以及如何在项目中使用它们来提高代码的可维护性和可读性。文章将通过实例代码,详细解析命名空间的使用规则和自动加载机制的工作原理,帮助读者更好地理解和应用这两个特性。
15 0
|
29天前
|
PHP 开发者
深入理解PHP的命名空间与自动加载机制
【2月更文挑战第30天】在现代PHP开发中,命名空间和自动加载机制是两个重要的特性,它们为代码的组织和重用提供了强大的支持。本文将深入探讨PHP中的命名空间概念,并详细解析自动加载机制的原理及其实现方法。通过阅读本文,读者可以掌握如何有效地使用命名空间来避免名称冲突,以及如何利用自动加载机制提高代码的可维护性和性能。
|
29天前
|
PHP 开发者
深入理解PHP的命名空间与自动加载机制
【2月更文挑战第30天】在PHP的编程实践中,命名空间和自动加载机制是实现代码组织和维护的重要工具。本文将探讨命名空间的概念、如何合理地使用它们来避免名称冲突,并深入解析自动加载机制的原理及其在现代PHP框架中的应用。通过理解这些核心概念,开发者可以编写出更加模块化、易于维护的PHP代码。
|
3天前
|
PHP 开发者
深入理解PHP中的命名空间与自动加载机制
【4月更文挑战第16天】在PHP的编程实践中,命名空间和自动加载机制是两个核心概念,它们不仅提高了代码的可维护性,还增强了代码的复用性。本文将详细探讨PHP中命名空间的概念、实现及其与自动加载机制的结合使用,帮助开发者构建更加模块化和易于管理的PHP应用程序。通过实例分析,我们将了解如何有效地利用这些特性来优化项目结构,减少代码冗余,并避免潜在的命名冲突。
9 4
|
22天前
|
PHP 开发者
深入理解PHP中的命名空间与自动加载机制
在现代PHP开发实践中,命名空间和自动加载机制是模块化和代码复用的关键概念。本文将详细探讨PHP中的命名空间如何帮助我们避免命名冲突,以及自动加载机制如何优化我们的应用程序性能。通过实例演示和分析,读者将能够掌握这两个高级特性的使用,并了解它们是如何影响代码组织和维护的。