laravel - php 的 namespace 和 autoload 的问题

WBOY
Freigeben: 2016-06-06 20:12:41
Original
1196 Leute haben es durchsucht

假设我的项目其中的一个目录:

<code>app
== site
==== controller
====== IndexController.php
====== AccessController.php
== api
==== controller
====== PostController.php
</code>
Nach dem Login kopieren
Nach dem Login kopieren

假设 IndexController.php 的内容:

<code>namespace app\site\controller;

class IndexController {
    // some code
}
</code>
Nach dem Login kopieren
Nach dem Login kopieren

项目是单入口,包含了 function autoload($className),我的问题:

假设项目约定了 namespace 中的名称必须和文件夹名称一致,并且类名称也和类文件同名(不包含下划线等奇怪的字符),那这样的话,$className 其实只需要把右斜杠换成 DIRECTORY_SEPARATOR 就可以找到对应的类文件了,比如:

<code>$obj = new \app\site\controller\IndexController();
</code>
Nach dem Login kopieren
Nach dem Login kopieren

或者

<code>class TestClass extends \app\site\controller\IndexController {}
</code>
Nach dem Login kopieren
Nach dem Login kopieren

那 autoload 实际找到的就是 /app/site/controller/IndexController.php。

既然这样,那为什么 thinkphp 里面的 Think 类还要 $_map 呢?类似的还有 laravel 里的:

<code>autoload_namespaces.php
autoload_classmap.php
autoload_psr4.php
</code>
Nach dem Login kopieren
Nach dem Login kopieren

比如这个是 autoload_psr4.php 里的内容:

<code>$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'yii\\swiftmailer\\' => array($vendorDir . '/yiisoft/yii2-swiftmailer'),
    'yii\\gii\\' => array($vendorDir . '/yiisoft/yii2-gii'),
    'yii\\faker\\' => array($vendorDir . '/yiisoft/yii2-faker'),
    'yii\\debug\\' => array($vendorDir . '/yiisoft/yii2-debug'),
    'yii\\composer\\' => array($vendorDir . '/yiisoft/yii2-composer'),
    'yii\\codeception\\' => array($vendorDir . '/yiisoft/yii2-codeception'),
    'yii\\bootstrap\\' => array($vendorDir . '/yiisoft/yii2-bootstrap'),
    'yii\\' => array($vendorDir . '/yiisoft/yii2'),
    'cebe\\markdown\\' => array($vendorDir . '/cebe/markdown'),
    'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
);
</code>
Nach dem Login kopieren
Nach dem Login kopieren

这里面通过数组定义的映射有什么作用啊?

回复内容:

假设我的项目其中的一个目录:

<code>app
== site
==== controller
====== IndexController.php
====== AccessController.php
== api
==== controller
====== PostController.php
</code>
Nach dem Login kopieren
Nach dem Login kopieren

假设 IndexController.php 的内容:

<code>namespace app\site\controller;

class IndexController {
    // some code
}
</code>
Nach dem Login kopieren
Nach dem Login kopieren

项目是单入口,包含了 function autoload($className),我的问题:

假设项目约定了 namespace 中的名称必须和文件夹名称一致,并且类名称也和类文件同名(不包含下划线等奇怪的字符),那这样的话,$className 其实只需要把右斜杠换成 DIRECTORY_SEPARATOR 就可以找到对应的类文件了,比如:

<code>$obj = new \app\site\controller\IndexController();
</code>
Nach dem Login kopieren
Nach dem Login kopieren

或者

<code>class TestClass extends \app\site\controller\IndexController {}
</code>
Nach dem Login kopieren
Nach dem Login kopieren

那 autoload 实际找到的就是 /app/site/controller/IndexController.php。

既然这样,那为什么 thinkphp 里面的 Think 类还要 $_map 呢?类似的还有 laravel 里的:

<code>autoload_namespaces.php
autoload_classmap.php
autoload_psr4.php
</code>
Nach dem Login kopieren
Nach dem Login kopieren

比如这个是 autoload_psr4.php 里的内容:

<code>$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'yii\\swiftmailer\\' => array($vendorDir . '/yiisoft/yii2-swiftmailer'),
    'yii\\gii\\' => array($vendorDir . '/yiisoft/yii2-gii'),
    'yii\\faker\\' => array($vendorDir . '/yiisoft/yii2-faker'),
    'yii\\debug\\' => array($vendorDir . '/yiisoft/yii2-debug'),
    'yii\\composer\\' => array($vendorDir . '/yiisoft/yii2-composer'),
    'yii\\codeception\\' => array($vendorDir . '/yiisoft/yii2-codeception'),
    'yii\\bootstrap\\' => array($vendorDir . '/yiisoft/yii2-bootstrap'),
    'yii\\' => array($vendorDir . '/yiisoft/yii2'),
    'cebe\\markdown\\' => array($vendorDir . '/cebe/markdown'),
    'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
);
</code>
Nach dem Login kopieren
Nach dem Login kopieren

这里面通过数组定义的映射有什么作用啊?

composer里的自动加载可以支持四种规范,psr-0(autoload_namespaces.php),psr-4,class-map,还有files,你如果自己写代码,这样约定好了,命名空间和路径保持一致,然后autoload加载按路径加载,当然不需要classmaps,但是很多类库是其他人写的,每个人习惯不一样,有的人喜欢psr-4,有的人喜欢psr-0,(大家规范都一样,声明的命名空间和路径不一样)时,就需要你说的 Classmap了,你可以看下composer的loader类

laravel里面的autoload_psr4.php是composer根据各个包的composer.json自动生成的,你研究一下composer就明白了

自动加载不止是你看到的能直接

<code>$obj = new \app\site\controller\IndexController();</code>
Nach dem Login kopieren

这些都已经是自动加载后的结果了。
如果没有自动加载,你这样子根本不能实现对象。

你脱离框架再这么写看看?

composer的自动加载是根据psr规则来的。

举个小例子:
如果你要实现一个工厂类,自动加载该如何实现?
题主可以试一下,就知道框架为什么要这么做了。

Composer的自动加载还可以自定义映射的,不一定是按平常的目录自动加载,可以看下Composer的文档,架构那一章,有说明每一个key的含义。

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage