(4)引入命名空间和类的自动加载

发布于:2022-08-24 12:05:21

一、入口文件(index.php)

<?php

define('APP_PATH', dirname(__DIR__) . ''); //定义APP主目录,用于自动加载,后期引入composer后可以省略
define('VIEW_PATH', dirname(__DIR__) . '/view'); //定义视图主目录,用于控制器加载视图

include_once '../core/autoload.php';

(new corecore())->start();

二、抽象核心(core.php)

<?

namespace core;

class core
{
    // public function __construct()
    // {
    // }

    public function start()
    {
        $app = $this->getApp();
        $this->callFunction($app);
    }
    /**
     * 生成用户应用实例
     */
    public function getApp()
    {
        $c = isset($_GET['c']) ? $_GET['c'] : 'app\\app'; //控制器

        
        /*autoload已经引入自动加载机制,下边这一段可以省略了
        $appFile = '../app/' . $c . '.php'; //此处可以看到控制器名与文件名需要同名
        if (!file_exists($appFile)) {
            throw new \Exception("用户APP不存在:" . $c);
        }
        include $appFile; 
        */


        return new $c();
    }

    /**
     * 获取用户应用方法
     */
    public function callFunction($app)
    {
        $f = isset($_GET['f']) ? $_GET['f'] : 'index'; //方法
        if (!method_exists($app, $f)) {
            throw new \Exception("用户方法不存在:" . $f);
        }
        return $app->$f();
    }
}

三、自动加载器(autoload.php)

<?php

//参考文档:https://www.php.net/manual/zh/function.spl-autoload-register.php

class autoload
{
    /**
     * 自动加载
     */
    public static function loader($class)
    {
        // var_dump($class);
        if (false !== strpos($class, '\')) { //用户类不以开头
            $filename = str_replace('\', '/', $class) . '.php'; //引入命名空间后,传入的参数$class包含完整的命名空间和类名,此处替换为/并加上.php结尾,用于include原始文件
            $FirstNamespace = substr($filename, 0, strpos($filename, '/')); //获取命名空间的第一段,一般用这种方法对应空间主目录
            switch ($FirstNamespace) {
                case 'core':
                    $filename = dirname(__DIR__) . '/' . $filename; //core目录目前与autoload在同一目录下,用这种方式拼接出完整目录
                    break;
                case 'app':
                    $filename = APP_PATH . '/' . $filename; //core目录目前与autoload在同一目录下,用这种方式拼接出完整目录
                    break;
                default:
                    $filename = dirname(__DIR__)  . '/' . $filename; //默认的加载目录,后边再改造
            }
            // print_r(is_file($filename) . '====' . $class . '====' . $filename . PHP_EOL);
            if (is_file($filename)) {
                include $filename; //加载文件,自动加载的核心
            }
        }
    }
}

spl_autoload_register(array('autoload', 'loader'), true);

三、引用控制器和视图

1、控制器app.php

<?php

namespace app;

class app
{
    public function index()
    {
        $name = "世界";
        include VIEW_PATH . '/' . substr(__CLASS__, strpos(__CLASS__, '\')) . '/' . __FUNCTION__ . '.php'; //__CLASS__获取的类名带有命名空间,需要切除第一段目录名
    }
}

2、视图view.php

<html>

<head></head>

<body>
    <h2>你好<?php echo $name; ?></h2>
</body>

</html>

四、目录结构如下

附件:点击下载
阅读 635