Heim  >  Artikel  >  Backend-Entwicklung  >  PHP命名空间的加载问题

PHP命名空间的加载问题

WBOY
WBOYOriginal
2016-09-23 11:31:041202Durchsuche

假设现在的目录结构是这样的:
PHP命名空间的加载问题

在A.php里面代码是:

namespace A;
class A{
public function __construct()
{
echo 'AAAAAAAAAAAA';
}
}

在B.php里面代码是:
namespace B;
use A\A;
new A();
?>

报错:Fatal error: Class 'AA' not found in 。。。

我对php的命名空间命名规则一直存在疑惑:

  1. php到底会不会自动根据命名空间的名字加载那个类?

  2. 是不是就算使用了命名空间,在一个文件调用另一个文件的类的时候,也要使用require、include等把另一个类文件加载到当前文件才能实例化使用

  3. 如果上面第2点YES的话,是不是就是使用autoload等方式来加载?是不是所谓的命名空间其实就是个用来区别类的名字而已,并没有自动加载类的作用?

回复内容:

假设现在的目录结构是这样的:
PHP命名空间的加载问题

在A.php里面代码是:

namespace A;
class A{
public function __construct()
{
echo 'AAAAAAAAAAAA';
}
}

在B.php里面代码是:
namespace B;
use A\A;
new A();
?>

报错:Fatal error: Class 'AA' not found in 。。。

我对php的命名空间命名规则一直存在疑惑:

  1. php到底会不会自动根据命名空间的名字加载那个类?

  2. 是不是就算使用了命名空间,在一个文件调用另一个文件的类的时候,也要使用require、include等把另一个类文件加载到当前文件才能实例化使用

  3. 如果上面第2点YES的话,是不是就是使用autoload等方式来加载?是不是所谓的命名空间其实就是个用来区别类的名字而已,并没有自动加载类的作用?

首先要清楚命名空间是干啥的,命名空间正如其名,是声明自己所在空间的名称(classes\tool:相当于宣布——我在classes空间位置中的tool空间中),换句话说就是表面自己在什么位置,你用use引入的命名空间,说到底只是引入了一个“位置名”,真身并没被include或require引入过来,php引入真身须通过include或require,脱离了这两个是不可能的。

我们看到的__autoload、spl_autoload_register属于php的魔术引入法(其实这种概念类似于面向对象中的控制反转(个人理解)),魔术引入——通俗点来说就是生产一个魔法箱,这个魔法箱负责帮你处理繁琐的include、require这些累活。如果想实现通过命名空间的自动加载,你需要按规矩来,规矩就是:psr-0自动加载规范,如果按规矩声明了位置名,通过use引入的“位置名”就能被魔法箱解析,解析了它的位置名后,按图索骥,然后通过include或require导入对应的文件。

总结起来就这三点:

  1. use引入的只是空间名称,真身并没引入;

  2. php引入php文件必须要走require和include;

  3. 万变不离其宗,不要被假象所迷糊

参考资料:

  1. Autoload 自動載入

  2. composer自动加载解析

  3. 可以用ide工具看看php相关框架(比如laravel)的自动解析源码

  1. 肯定不会自动加载, 除非你设置了 spl_autoload_register().

  2. 是的, 还是要使用require_once或者include_onece这类的函数加载类文件.

  3. 命名空间可以看成目录, 不同的目录可以有相同的文件名称, 避免命名冲突. 命名空间不具备自动加载类的作用.

1.不会自动加载

<code>自动加载:
    类库映射
    PSR-4自动加载检测
    PSR-0自动加载检测
</code>

2.在TP5,可以用use 关键字即可, 不需要做require这样繁琐的操作了
3.已经该用spl_autoload_register了替代autoload, composer的出现不就是为了解决这种加载问题么?所以一定要设置命名空间,命名空间不具有自动加载类的作用,他是为了避免命名冲突和可视化类的路径和真正的懒加载等。

使用spl_autoload_register注册了自动装载函数才能使用use,demo:

<code><?php class Autoload
{
    /**
     * 类映射
     * @var array
     */
    // private static $_classMap = [];

    public function __construct()
    {
        # code...
    }
    
    public static function init()
    {
        spl_autoload_register('Autoload::autoload');
    }

    public static function autoload($class_name='')
    {
        // if (self::$_classMap[$class_name]) {
        //     require(self::$_classMap[$class_name]);
        // }
        require(str_replace('\\', '/', $class_name).'.php');
    }

}


/* register autoload funxtion|注册自动装载函数 */
require('./Autoload.php');
Autoload::init();</code></code>

  1. pho不会自动加载类。spl_autoload的加载是从include配置中找对应的 类名.inc或者 类名.php来加载。(具体查看 php文档)

  2. ThinkPHP和Laravel以及Composer之类的框架程序,都是通过spl_autoload_resigster来实现按照一定功能加载类。

  3. 命名空间设置的初衷是为了区分不同区的同名类,不一定是按照文件夹来命名,命名空间相当于对类进行分区,比如,你有个类叫 Router 我也有个类叫 Router,类名重复了,这时命名空间就可以起作用了。

  4. 我的回答是是,ThinkPHP的原理是通过 命名空间 来解析成 路径 ,再注册了autoload来加载, 如 abc,会在指定目录找a/bc.class.php (.class.php是tp指定的加载后缀,指定目录通常是library ),Zend 框架是通过 _ 来分割路径,如 a_b_c 类。会变成 /a/b/c.php来在指定目录找。

去了解下php面向对象设计模式 他们说的就是这些

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn