关于自动加载

第2天学习面向对象和mvc的小白,希望各位师傅能够说的详细一些,谢谢^_^
问题1:load函数里面的变量$classname的值从哪里来,为什么我没赋值他就有值且等于IndexController
问题2:按照run()方法里的的函数调用顺序先调用autoload()然后调用dispatch()方法是没问题,但是为什么dispatch()方法的执行在load()之前,而dispatch()里的$controller->$action_name();又在load()之后?
问题3:spl_autoload_register(array(__CLASS__,'load'));不太理解这句代码括号里的内容?
<?php
//核心启动类
Class Framework{

//run方法
public static function run(){
    //echo "hello,world!";
    self::init();
    self::autoload();
    self::dispatch();
}

//初始化方法
private static function init(){
    //路径的常量
    define("DS", DIRECTORY_SEPARATOR);
    define("ROOT",getcwd() . DS);//根路径
    define("APP_PATH", ROOT . "application" . DS);
    define("FRAMEWORK_PATH", ROOT . "framewrk" . DS);
    define("PUBLIC_PATH", ROOT . "public" . DS);
    define("CONFIG_PATH", APP_PATH . "config" . DS);
    define("CONTROLLERS_PATH", APP_PATH . "controllers" . DS);
    define("MODELS_PATH", APP_PATH . "models" . DS);
    define("VIEWS_PATH", APP_PATH . "views" . DS);
    define("CORE_PATH", FRAMEWORK_PATH . "core" . DS);
    define("DATABASES_PATH", FRAMEWORK_PATH . "databases" . DS);
    define("HELPER_PATH", FRAMEWORK_PATH . "helpers" . DS);
    define("LIBRARIES_PATH", FRAMEWORK_PATH . "libraries" . DS);
    define("UPLOAD_PATH", PUBLIC_PATH . "uploads" . DS);
    //index.php?p=admin&c=goods&a=add--admin后台的GoodsController中的addaction
    define("PLATFORM", isset($_GET['p']) ? $_GET['p'] : "admin");
    define("CONTROLLER", isset($_GET['c']) ? ucfirst($_GET['c']) : "Index");
    define("ACTION", isset($_GET['a']) ? $_GET['a'] : "index");
    define("CUR_CONTROLLER_PATH", CONTROLLERS_PATH . PLATFORM . DS);
    define("CUR_VIEW_PATH", VIEWS_PATH . PLATFORM . DS);
}
//路由分发, 实例化对象调用方法
//index.php?p=admin&c=goods&a=add--admin后台的GoodsController中的addaction
private static function dispatch(){
    $controller_name = CONTROLLER . "Controller";//GoodsController.php
    echo $controller_name."-dispatch<br>";//测试查看执行顺序
    $action_name = ACTION . "Action";//GoodsController.php里面的addAction方法
    //实例化对象
    $controller = new $controller_name();//实例化GoodsController
    //调用方法
    $controller->$action_name();//调用GoodsController里面的addAction方法
}
//自动载入
//此处,只加载application中的controller和model
private static function autoload(){
    echo "_autoload1<br>";//测试查看执行顺序
    spl_autoload_register(array(__CLASS__,'load'));
    echo "_autoload2<br>";//测试查看执行顺序
}
//完成指定类的加载
//只加载application中的controller和model,如GoodsController,BrandModel
public static function load($classname){
    echo $classname."_load<br>";//测试查看执行顺序
    if(substr($classname, -10) == 'Controller'){
        //控制器
        include CUR_CONTROLLER_PATH . "{$classname}.class.php";
    }else if (substr($classname, -5) == 'Model') {
        include CUR_VIEW_PATH . "{$classname}.class.php";
    }else {
        //暂略
    }
}

}
?>

clipboard.png

阅读 2.5k
3 个回答

问题1 ,问题3答案 看看这个就明白了几个 PHP 的“魔术常量”

问题2:

private static function autoload(){
    echo "_autoload1<br>";//测试查看执行顺序
    spl_autoload_register(array(__CLASS__,'load'));
    echo "_autoload2<br>";//测试查看执行顺序
} 

这段代码是说,如果遇到要寻找类的时候,通过这里注册的load方法来找,但是还没有遇到,只是先声明一下。

接下来:

 //实例化对象
    $controller = new $controller_name();//实例化GoodsController
    //调用方法
    $controller->$action_name();//调用GoodsController里面的addAction方法

这里就真的遇到了, 你要new一个还没找到的类,他怎么找呢? 就通过你刚才注册的方法load方法,通过魔术变量__CLASS__参数,根据函数寻找方法加载类。

所以顺序是,

  • 先注册

  • 分发(dispathc)请求

  • 解析要寻找哪个类

  • 然后加载该类

  • 然后执行方法

// test.php

<?php
// 注册自加载
spl_autoload_register('autoload');

function autoload($className)
{
  // 你打印看看
  var_dump($className);die;
}

/************************************* test *************************************/

use Test\TestClass;

$test = new TestClass();

// TestClass.php

<?php
namespace Test;

/**
 *
 */
class TestClass
{

  function __construct()
  {
    # code...
  }
}

// 运行

php test.php

// 输出

string(14) "Test/TestClass"

__autoload魔术方法,自动加载类,但是一般框架都用自己的方法,利用spl_autoload_register()可以注册一到多个,
如果某个类声明了命名空间如coreConfig,可以coreConfig::xxx(),此时会自动引入该类

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题