在使用類的時候會用 require
或 include
將類加載進來,可是每次都手動加載,會致使一系列問題,好比類重複加載,管理困難等。因此解決上述問題,咱們使用單獨的一個文件來完成全部類的自動加載。php
該函數能夠註冊任意數量的自動加載器,當使用還沒有被定義的類(class)和接口(interface)時自動去加載。經過註冊自動加載器,腳本引擎在 PHP 出錯失敗前有了最後一個機會加載所需的類。html
儘管__autoload()
函數也能自動加載類和接口,但更建議使用 spl_autoload_register() 函數。spl_autoload_register()
提供了一種更加靈活的方式來實現類的自動加載(同一個應用中,能夠支持任意數量的加載器,好比第三方庫中的)。所以,再也不建議使用 __autoload() 函數,在之後的版本中它可能被棄用。
在 core
目錄下建立一個 Autoload.php
文件linux
$ cd tinyphp/core $ touch Autoload.php
編輯 Autoload.php
瀏覽器
// 命名空間和文件目錄映射 <?php $path = [ 'core' => 'core', 'app' => 'app', 'controller' => 'app/controllers', 'model' => 'app/models', 'view' => 'app/views', 'dispatcher' => 'core/dispatcher', ]; /** * 參數 $class 表示自動加載的類名 * * 匿名函數中使用 use 可使用外部變量 */ spl_autoload_register(function($class) use ($path) { //解析類名,若是使用了命名空間,則會查找 $path 中對於的路徑 $position = strripos($class,'\\'); $key = substr($class,0,$position); $value = $path[$key] ?? ''; $file = substr($class,$position+1).'.php'; require APP_PATH.'/'.$value.'/'.$file; });
spl_autoload_register()
主要實現類自動加載,參數使用的是匿名函數,經過關鍵字 use
可使用外部變量 $path,其做用是提供命名空間和路徑的對應關係,例如使用 namespace controller
,對應的類在路徑 app/controllers
。服務器
使用方式爲,在入口文件public/index.php
中,直接 require 該文件便可。app
<?php define('APP_PATH',dirname(__DIR__)); require APP_PATH.'/core/Autoload.php';
而後咱們在core
文件夾下建立一個名爲 Application.php
並編輯內容框架
<?php namespace core; class Application { public function run() { echo 'hello world'; } }
自動加載完成,待會啓動(註冊)框架以後就能夠看到效果了。函數
有時候須要在框架啓動時,額外加載一些應用配置或用戶定義的方法,好比定義常量,加載自定義輔助函數等。ui
咱們在應用目錄 app
中建立一個啓動腳本 Bootstrap.php
,規定該腳本內全部以 init
的方法都會被調用,並在 Application
類的構造函數中調用該腳本this
建立 app/Bootstrap.php
,編輯內容
<?php namespace app; class Bootstrap { /** * 全部以 init 開始的函數都會被依次調用 * */ public function initConst() { echo 'Bootstrap : 1'.PHP_EOL; } public function initHelper() { echo 'Bootstrap : 2'.PHP_EOL; } }
在 Application
類中添加啓動項
__construct()
中獲取 Bootstrap
實例。run()
方法中遍歷 Bootstrap
類中以 init
開頭的方法並執行。<?php //這裏用...省略以前的代碼,在實際操做中,須要完整的代碼,否則會報錯 ... public $boot; public function __construct() { /** * \app\爲命名空間, * 第一個\表示在根目錄,否在表示在當前命名空間下的子目錄 * * 例如,app\Bootstrap() 表示在類在 tinyphp/core/app 目錄下 * \app\Bootstrap() 則表示在 tinyphp/app 目錄下 */ $this->boot = new \app\Bootstrap(); } public function run() { /** * 執行啓動項 * 全部init開頭的方法都會被調用 * */ foreach(get_class_methods($this->boot) as $func) { if (0 === strpos($func, 'init')) { call_user_func([$this->boot,$func]); } } } ...
在入口文件 index.php 中啓動框架,並執行 run()
方法
<?php use \core\Application; define('APP_PATH',dirname(__DIR__)); require APP_PATH.'/core/Autoload.php'; (new Application())->run();
進入 public
目錄,兩種方式執行 php
$ php index.php Bootstrap : 1 Bootstrap : 2
$ php -S localhost:8080
在瀏覽器輸入 http://localhost:8080 , 結果以下
Bootstrap : 1Bootstrap : 2
從結果能夠看出,Application
類在實例化的時候執行構造函數,構造函數中完成了啓動項的方法調用。
本節實現了一個簡單的類自動加載和框架的核心類,在啓動時加載用戶啓動項,在 app/Bootstrap.php
中全部以 init
開頭的方法都會被依次調用。
下期見