命名空间与自动加载系列(六)--自动加载(完)

作者: 温新

分类: 【PHP基础】

阅读: 1994

时间: 2021-05-17 11:28:09

为什么要使用类的自动加载?

前面可以看到,使用到其它类时需要通过include关键字将其引入,如果有N多个需要通过include来引入,不太现实,为了解决这个问题,可以使用类的自动加载。

__autoload已经被废弃,旧代码中可能还可以看到。现在推荐使用sqp_autoload_register

准备测试目录与文件,结构如下:

<span style="box-sizing: border-box;padding-right: 0.1px">demo01</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> bootstrap.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> App</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  Controller</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">   Index.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">   Post.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  Module</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">   Post.php</span>

每个文件内容如下:

<span style="box-sizing: border-box; padding-right: 0.1px;">// App/Controller/Index.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style=""><?</span><span style="">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">namespace</span> <span style="">App\Controller</span>;</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">class</span> <span style="">Index</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">public</span> <span style="">static</span> <span style="">function</span> <span style="">index</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">echo</span> <span style="">'Index控制器:'</span> . <span style="">__METHOD__</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">// App/Controller/Post.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style=""><?</span><span style="">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">namespace</span> <span style="">App\Controller</span>;</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">class</span> <span style="">Post</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">public</span> <span style="">static</span> <span style="">function</span> <span style="">index</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">echo</span> <span style="">'Post控制器:'</span> . <span style="">__METHOD__</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">// App/Module/Post.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style=""><?</span><span style="">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">namespace</span> <span style="">App\Module</span>;</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">class</span> <span style="">Post</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">public</span> <span style="">static</span> <span style="">function</span> <span style="">index</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">echo</span> <span style="">'Post模型:'</span> . <span style="">__METHOD__</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

方式一,使用函数方式实现自动加载

<span style="box-sizing: border-box; padding-right: 0.1px;">// App/bootstrap.php</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style=""><?</span><span style="">php</span></span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">// 自动加载类文件</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">/**</span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">* @param string $class 类的命名空间,如 App\Controller\Index</span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">*/</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">spl_autoload_register</span>(<span style="">function</span>(<span style="">$class</span>){</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">// 将命名空间命名路径转为文件路径</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">$fileName</span> <span style="">=</span> <span style="">str_replace</span>(<span style="">'\\'</span>, <span style="">'/'</span>, <span style="">$class</span>) . <span style="">'.php'</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">require</span> <span style="">$fileName</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">});</span>
<span style="box-sizing: border-box; padding-right: 0.1px;">// App/index.php</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style=""><?</span><span style="">php</span></span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">include</span> <span style="">'./bootstrap.php'</span>;</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">use</span> <span style="">App\Controller\Index</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">use</span> <span style="">App\Module\Post</span>;</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">Index</span>::<span style="">index</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">Post</span>::<span style="">index</span>();</span>

使用函数方式实现类的自动加载完成。需要使用哪一个类直接引入(当然了,这个类是要存在的,不然要报错咯)。

方式二,使用面向对象方式实现

现在来bootstrap.php改造为面向对象

<span style="box-sizing: border-box; padding-right: 0.1px;">// App/bootstrap.php</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">?</span><span style="">php</span></span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">namespace</span> <span style="">App</span>;</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box; padding-right: 0.1px;">// 自动加载类文件</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">class</span> <span style="">Bootstrap</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">public</span> <span style="">static</span> <span style="">function</span> <span style="">boot</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">// 实例化自身并调用autoload方法</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">spl_autoload_register</span>([<span style="">new</span> <span style="">self</span>, <span style="">'autoload'</span>]);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="">public</span> <span style="">function</span> <span style="">autoload</span>(<span style="">string</span> <span style="">$class</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">echo</span> <span style="">$class</span>;<span style="">die</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">$fileName</span> <span style="">=</span> <span style="">str_replace</span>(<span style="">'\\'</span>, <span style="">'/'</span>, <span style="">$class</span>) . <span style="">'.php'</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="">require</span> <span style="">$fileName</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="">Bootstrap</span>::<span style="">boot</span>();</span>

方式三,使用composer实现自动加载

1)删除bootstrap.php文件

2)使用composer进行初始化

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="">cd</span> demo</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">composer init</span><br></br><span style="padding-right: 0.1px; box-sizing: border-box;"></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">This command will guide you through creating your composer.json config.</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">Package name (<vendor>/<name>) [root/demo]:</span>

执行composer init出现的一系列东西暂时不用管,直接回车即可。

如是出现 Author [, n to skip]: Invalid author string. Must be in the format: John Smith john@example.com

输入 n 跳过

执行完composer init后,根目录中多出一个composer.json文件,其内容如下:

<span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span class="cm-string cm-property" style="">"name"</span>: <span style="">"45796/demo"</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span class="cm-string cm-property" style="">"require"</span>: {}</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

3)修改composer.json

<span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span class="cm-string cm-property" style="">"name"</span>: <span style="">"45796/demo"</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span class="cm-string cm-property" style="">"require"</span>: {},</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span class="cm-string cm-property" style="">"autoload"</span>:{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span class="cm-string cm-property" style="">"psr-4"</span>: {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">      <span class="cm-string cm-property" style="">"App\\"</span>:<span style="">"App"</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

自动加载遵循psr-4规范,"App\\":"App"的关系时,"命名空间":"对应的文件夹"

4)生成自动加载

composer install # 执行结果 No lock file found. Updating dependencies instead of installing from lock file. Use composer update over composer install if you do not have a lock file. Loading composer repositories with package information Updating dependencies Nothing to modify in lock file Writing lock file Installing dependencies from lock file (including require-dev) Nothing to install, update or remove Generating autoload files

执行成功后,会在应用根目录生成vendor目录,其中就包含自动加载的文件

5)使用自动加载

index.php文件中引入并使用自动加载

// index.php <?php include './vendor/autoload.php'; use App\Controller\Index; use App\Module\Post; Index::index(); Post::index();

加载文件案例

使用composer自动加载后,还可以自动加载文件。TP框架中有一个common.php文件,可以存放通用文件。以Laravel文件,如想要添加一个公用的助手函数文件,其没有直接提供,此时就可以通过composer自动加载文件实现。

第一步:修改compsoer.json

{     "name": "45796/demo",     "require": {},     "autoload":{      "files":[      "Help/Helper.php"      ],      "psr-4": {      "App\\":"App"      }     } }

第二步:应用中添加对应的文件

// 文件位置:App/Help/Helper.php <?php function show() { echo '公共文件'; }

第三步:composer更新

composer update

第四步:使用

<?php      
show();

命名空间系列完

请登录后再评论