博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
yii2 源码分析1从入口开始
阅读量:5024 次
发布时间:2019-06-12

本文共 11459 字,大约阅读时间需要 38 分钟。

我是在  backend 一步步打印的   很多地方我也是很模糊 。后来发现一位大神的文章(http://www.yiichina.com/tutorial/773)  参考文章自己动手开始写的  至于后来的 第一遍 很粗糙 慢慢完善。 希望对自己有帮助  希望各位积极指点 和后面不详细的地方 作补充。 我也会继续完善 。 先从入口开始 $application = new yii\web\Application($config);  //实例化 Application
$application->run();
这是  Application 的方法
class Application extends \yii\base\Application
在Application类中 首先看有没有构造方法  没有找到  so  就去父类中找(\yii\base\Application)
在\yii\base\Application
..........    public function __construct($config = [])    {        Yii::$app = $this;  // $this  代表  object(yii\web\Application)        static::setInstance($this);  //  在这个方法中把这个类中所有的方法属性都放到一个数组中@@@@@请看下面        $this->state = self::STATE_BEGIN;        $this->preInit($config);  //看下面有解释        $this->registerErrorHandler($config);//暂不做解释  加载异常类  以后研究          Component::__construct($config);    }..........
@@@@@
public static function setInstance($instance) {
if ($instance === null) {    //$instance不为空 代表的$this(object(yii\web\Application))
unset(Yii::$app->loadedModules[get_called_class()]);     } else {              //get_class($instance)   ->  "yii\web\Application"         Yii::$app->loadedModules[get_class($instance)] = $instance;     } } 这样 Yii::$app  就可以调用 该类中的方法 属性  以及父类中的方法。

$this->preInit($config);// 

*****preInit****方法

主要是获取到配置文件中的数据  处理配置文件的数据 设置别名等等
public function preInit(&$config) {
if (!isset($config['id'])) {
throw new InvalidConfigException('The "id" configuration for the Application is required.'); } if (isset($config['basePath'])) {
$this->setBasePath($config['basePath']); //拿这个做例子 unset($config['basePath']); 。。。部分代码省略。。。。。   
  public function setBasePath($path)   {              
      var_dump($path);die;   //     "/var/www/testyii2/backend"
   parent::setBasePath($path);     //该方法中设置 $this->_basePath = $app;  $app=/var/www/testyii2/backend
  Yii::setAlias('@app', $this->getBasePath());   so  此时  @app  就等于  /var/www/testyii2/backend
  } 好了现在回到  preInit()方法中 *******end*****
$this->registerErrorHandler($config);简单看下吧
$this->set('errorHandler', $config['components']['errorHandler']); 我打印了下  var_dump($this->get('errorHandler'))   应该是  定义一些错误方法和属性等等 看下图
 
最后看这个方法
Component::__construct($config);  调用了 object 方法中的 构造方法
object(类):  public function __construct($config = []) {
if (!empty($config)) {
Yii::configure($this, $config);  //找到Yii类 该类中没有configure 方法 然而继承了 baseyii so 去baseyii类中找                           // } $this->init(); }
。。。。。
//baseyii类 public static function configure($object, $properties) {
foreach ($properties as $name => $value) {
$object->$name = $value; } return $object; } //该方法 中 $object ==object类 循环吧配置文件中的 数据 复制给 object对象中的属性和值  最终由于object 是yii\web\Application 的最终父类 还有在上面中定义了别名@app

  // so  可以Yii::$app->配置参数来访问配置文件中的内容

****end*** 分析
$this->init();  在object类中   class Component extends Object  component继承的object
Component::__construct($config);   在base/Application  继承了 Module 类 so 看module 中的init方法()
//module 中的init 方法       public function init()    {        if ($this->controllerNamespace === null) {  //取出控制器命名空间。            $class = get_class($this);            if (($pos = strrpos($class, '\\')) !== false) {                $this->controllerNamespace = substr($class, 0, $pos) . '\\controllers';            }        }    }

完毕

回到起点 看index.php中的

$application->run();   在Application类中没有找到run方法   Application 继承 base\Application类

\yii\base\Application.php   中的run方法

public function run()    {        try {            $this->state = self::STATE_BEFORE_REQUEST;            $this->trigger(self::EVENT_BEFORE_REQUEST);  加载事件函数函数的            $this->state = self::STATE_HANDLING_REQUEST;            $response = $this->handleRequest($this->getRequest());  //这里的this调用的是  yii\web\Application.php 中的方法看下面
        $this->state = self::STATE_AFTER_REQUEST;            $this->trigger(self::EVENT_AFTER_REQUEST);    //加载事件函数函数的
        $this->state = self::STATE_SENDING_RESPONSE; $response->send();       $this->state = self::STATE_END; return $response->exitStatus; }      catch (ExitException $e) {
         $this->end($e->statusCode, isset($response) ? $response : null); return $e->statusCode; }       }
//web/Application 中的 handleRequest()    public function handleRequest($request)    {        if (empty($this->catchAll)) {            list ($route, $params) = $request->resolve();  //取出路由及参数        } else {            $route = $this->catchAll[0];            $params = $this->catchAll;            unset($params[0]);        }        try {            Yii::trace("Route requested: '$route'", __METHOD__);            $this->requestedRoute = $route;            $result = $this->runAction($route, $params);//运行控制器中的Acition,下面有详细介绍    base/application 中没有so 找到module 中的runaction()
if ($result instanceof Response) {                return $result;            } else {                $response = $this->getResponse();                if ($result !== null) {                    $response->data = $result;                }                return $response;            }        } catch (InvalidRouteException $e) {            throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'), $e->getCode(), $e);        }    }

 

// class Modulepublic function runAction($route, $params = [])    {        $parts = $this->createController($route);//根据路由创建控制器  看下面
if (is_array($parts)) {            /* @var $controller Controller */            list($controller, $actionID) = $parts;            $oldController = Yii::$app->controller;            Yii::$app->controller = $controller;            $result = $controller->runAction($actionID, $params);//创建方法执行控制器里的action  actionId ==index( 控制器/index(这里表示方法))            Yii::$app->controller = $oldController;            return $result;        } else {            $id = $this->getUniqueId();            throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');        }    }
$this->createController()
$this->createController()  //创建控制器public function createController($route)    {        if ($route === '') {            $route = $this->defaultRoute;        }        // double slashes or leading/ending slashes may cause substr problem        $route = trim($route, '/');        if (strpos($route, '//') !== false) {            return false;        }        if (strpos($route, '/') !== false) {            list ($id, $route) = explode('/', $route, 2);        } else {            $id = $route;            $route = '';        }echo   $route  //--->"backend/default/index"
// module and controller map take precedence
if (isset($this->controllerMap[$id])) {  //不进入         $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);         return [$controller, $route];     }     $module = $this->getModule($id);     if ($module !== null) {        //不进入         return $module->createController($route);     }     if (($pos = strrpos($route, '/')) !== false) {
$id .= '/' . substr($route, 0, $pos);   $route = substr($route, $pos + 1);   }
//$id = backend/default"   (模块/控制器)   $route =index   方法
$controller = $this->createControllerByID($id);  //下面分析用颜色查找     if ($controller === null && $route !== '') {  //进入         $controller = $this->createControllerByID($id . '/' . $route);     // 根据给定的控制器标识创建一个控制器。看下面         $route = '';     }     return $controller === null ? false : [$controller, $route]; }
 
public function createControllerByID($id) {
$pos = strrpos($id, '/'); if ($pos === false) {
$prefix = ''; $className = $id; } else {
$prefix = substr($id, 0, $pos + 1);    //backend 模块 $className = substr($id, $pos + 1);    //default 控制器 } if (!preg_match('%^[a-z][a-z0-9\\-_]*$%', $className)) { return null; }
// preg_match('%^[a-z0-9_/]+$%i', $prefix) ===1
if ($prefix !== '' && !preg_match('%^[a-z0-9_/]+$%i', $prefix)) {      
return null;     }
$className = str_replace(' ', '', ucwords(str_replace('-', ' ', $className))) . 'Controller';       $className = ltrim($this->controllerNamespace . '\\' . str_replace('/', '\\', $prefix)  . $className, '\\');     if (strpos($className, '-') !== false || !class_exists($className)) {
return null; }    if (is_subclass_of($className, 'yii\base\Controller')) {
$controller = Yii::createObject($className, [$id, $this]);  //创建了控制器对象 return get_class($controller) === $className ? $controller : null; } elseif (YII_DEBUG) {
throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller."); } else {
return null; } }
Yii/BaseYii.php
public static function createObject($type, array $params = []) {
if (is_string($type)) {
return static::$container->get($type, $params);  //返回请求类的是例 这边就不往下追了 本人能力有限啊 唉~无线惆怅中~~~ } elseif (is_array($type) && isset($type['class'])) {
$class = $type['class']; unset($type['class']); return static::$container->get($class, $params, $type); } elseif (is_callable($type, true)) {
return static::$container->invoke($type, $params); } elseif (is_array($type)) {
throw new InvalidConfigException('Object configuration must be an array containing a "class" element.'); } else {
throw new InvalidConfigException('Unsupported configuration type: ' . gettype($type)); } }
****end** 小部分结束(创建控制器部分) //承接上面的方法继续分析
$controller->runAction($actionID, $params);
namespace  yii\base;   //命名空间 class Controller extends Component implements ViewContextInterface{
public function runAction($id, $params = []) {
  $action = $this->createAction($id);  创建action  暂时不补全代码了 类啊。。。后续补上。   //打印$action  == yii\base\InlineAction 对象    if ($action === null) {
  throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);   }   Yii::trace("Route to run: " . $action->getUniqueId(), __METHOD__);   if (Yii::$app->requestedAction === null) {
   Yii::$app->requestedAction = $action;   }   $oldAction = $this->action;    //NULL   $this->action = $action;   $modules = [];   $runAction = true;   // call beforeAction on modules   // 加载默认模块如:Application log等。再调用模块内的beforeAction方法   foreach ($this->getModules() as $module) {
   if ($module->beforeAction($action)) {
   array_unshift($modules, $module);    } else {
   $runAction = false;    break;    }   } $result = null; if ($runAction && $this->beforeAction($action)) { //执行beforeAction // run the action $result = $action->runWithParams($params);   //执行控制器里的action $result = $this->afterAction($action, $result); //执行afterAction
// call afterAction on modules     foreach ($modules as $module) {
/* @var $module Module */ $result = $module->afterAction($action, $result); } } $this->action = $oldAction; return $result;
}
} //打印action  yii\base\InlineAction
public function runWithParams($params) {
$args = $this->controller->bindActionParams($this, $params); Yii::trace('Running action: ' . get_class($this->controller) . '::' . $this->actionMethod . '()', __METHOD__); if (Yii::$app->requestedParams === null) {
Yii::$app->requestedParams = $args; } return call_user_func_array([$this->controller, $this->actionMethod], $args); }

转载于:https://www.cnblogs.com/yhl664123701/p/5532135.html

你可能感兴趣的文章
ACID属性
查看>>
cnpm不是内部命令的解决方案:配置环境变量
查看>>
7系列FPGA远程更新方案-QuickBoot(转)
查看>>
导出帐号和权限脚本
查看>>
markdown公式编辑参考
查看>>
利用运行时给模型赋值
查看>>
归并排序求逆序对
查看>>
SQL2008用sql语句给字段添加说明
查看>>
JavaScript的对象创建
查看>>
树形DP(统计直径的条数 HDU3534)
查看>>
python学习之路(25)
查看>>
c++中拷贝构造函数、默认无参构造函数、析构函数的理解
查看>>
ActiveReports 报表控件官方中文入门教程 (3)-如何选择页面报表和区域报表
查看>>
kaggle竞赛
查看>>
区块链入门教程
查看>>
域 搭建OU 组织单元
查看>>
静态方法中调用非静态方法
查看>>
npm常用命令
查看>>
南海区行政审批管理系统接口规范v0.3(规划)4.2.【queryExpireList】当天到期业务查询...
查看>>
[置顶] 细说Cookies
查看>>