Yii2创建控制器(createController)方法详解

本文实例讲述了Yii2创建控制器(createController)方法。分享给大家供大家参考,具体如下:

yii中创建控制器的是在application中的request通过UrlManager解析得出路由信息的,然后再由yii\base\Module中的

public function runAction($route, $params = [])

方法来创建控制器,最后由控制器再执行相应的动作。

首先得明确,Yii中的路由分三种情况:

第一种是带有模块的(module id/controller id/action id),

第二种是带有命名空间(子目录)的(sub dir)/controller id/action id)

第三种是只有控制器和动作的(controller id/action id)

这三个有优先顺序,所以在创建控制器的时候,也是先查看是否是模块类型的路由,如果是,则获取这个模块,再由这个模块来创建控制器

接着再判断是否是第二种带有命名空间的。

public function createController($route)
{
  //如果路由为空,则使用默认的路由
  if ($route === '') {
    $route = $this->defaultRoute;
  }
  // double slashes or leading/ending slashes may cause substr problem
  //去掉首尾的反斜杠(“/”),如果路由中包含有“//”,则返回false创建失败。
  $route = trim($route, '/');
  if (strpos($route, '//') !== false) {
    return false;
  }
  /*
   * 路由分三种情况,
   * 一种是带模块id的(module id/controller id/action id),
   * 一种是有命名空间(子目录)的(sub dir)/controller id/action id)
   * 一种是只有控制器和动作的(controller id/action id)
   * 所以在这里要根据第一个“/”分隔成两部分,$id和$route信息,
   */
  if (strpos($route, '/') !== false) {
    list ($id, $route) = explode('/', $route, 2);
  } else {
    $id = $route;
    $route = '';
  }
  // module and controller map take precedence
  /*
   * 查看这个id是否是模块,如果是模块,则再用这个模块来创建控制器。
   * 所以,在如果一个控制器的名称和模块名称重复的话会优先创建模块里面的控制器。
   *
   * 如果有url: http://www.yii2.com/index.php?r=test/index
   * 本来是打算访问application中的控制器里面的test控制器,执行index动作的。
   *
   * 然而如果有个模块的名字为test,里面有个IndexController
   *
   * 根据上面会生成$id=test,$route=index
   *
   * 由于在下面查找存在这个模块,所以会执行这个test模块下面的index控制器,
   * 而不会执行application里面的test控制器的index动作
   */
  $module = $this->getModule($id);
  if ($module !== null) {
    return $module->createController($route);
  }
  //如果在controllerMap数组中指定了控制器映射,会优先根据这个里面的映射来创建控制器
  if (isset($this->controllerMap[$id])) {
    $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
    return [$controller, $route];
  }
  /*
   * 如果这个时候$route中还有“/”,也就是说原来的路由为home/index/aa
   * $id:home(不是模块)
   * $route:index/aa
   * 由于经过上面得知home不为模块,所以这个为命名空间(子目录),
   *
   * 再经过下面处理后为
   * $id:home/index 命名空间(子目录)home下面的index控制器
   * $route:aaa
   *
   */
  if (($pos = strrpos($route, '/')) !== false) {
    $id .= '/' . substr($route, 0, $pos);
    $route = substr($route, $pos + 1);
  }
    /*
     * $id:home/index
     * $route:aaa
     */
  $controller = $this->createControllerByID($id);
  if ($controller === null && $route !== '') {
      //如果创建失败,再加上route作为id再次创建
    $controller = $this->createControllerByID($id . '/' . $route);
    $route = '';
  }
  return $controller === null ? false : [$controller, $route];
}

在这个函数中$id就有两种情况,一种是前面带有命名空间的,一种是直接就一个控制器ID的。

public function createControllerByID($id)
{
    if (!preg_match('%^[a-z0-9\\-_/]+$%', $id)) {
      return null;
    }
    /*
     * 如果$id中有“/”,则前面的为目录,后面的为类
     *
     */
    $pos = strrpos($id, '/');
    if ($pos === false) {
      $prefix = '';
      $className = $id;
    } else {
      $prefix = substr($id, 0, $pos + 1);
      $className = substr($id, $pos + 1);
    }
    //生成控制器的类IndexController
    $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')) {
      return new $className($id, $this);
    } elseif (YII_DEBUG) {
      throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
    } else {
      return null;
    }
}

这个过程就结束了,然后再由创建出来的控制器执行它里面的动作

public 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);
    Yii::$app->controller = $oldController;
    return $result;
  } else {
    $id = $this->getUniqueId();
    throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
  }
}

更多关于Yii相关内容感兴趣的读者可查看本站专题:《Yii框架入门及常用技巧总结》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。

(0)

相关推荐

  • 详解PHP的Yii框架中的Controller控制器

    控制器是 MVC 模式中的一部分, 是继承yii\base\Controller类的对象,负责处理请求和生成响应. 具体来说,控制器从应用主体接管控制后会分析请求数据并传送到模型, 传送模型结果到视图,最后生成输出响应信息. 操作 控制器由 操作 组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个操作. 如下示例显示包含两个操作view and create 的控制器post: namespace app\controllers; use Yii; use app\models\

  • Yii2使用$this->context获取当前的Module、Controller(控制器)、Action等

    使用Yii2的时候,在某些场景和环境下需要获得Yii2目前所处于的module(模型).Controller(控制器).Action(方法),以及会调用控制器里面已经定义过的一些公共的方法等.对于这些问题Yii2可以在视图层View中使用$this->context这个对象去获得. 示例:譬如现在(视图层登陆界面)login.php方法下面: <?php //得到Yii2的当前的控制器Controller echo $this->context->id; //输出结果:site /

  • Yii控制器中filter过滤器用法分析

    本文实例讲述了Yii控制器中filter过滤器用法.分享给大家供大家参考,具体如下: 指定过滤动作,(如下projectContext()方法在新建,列表,管理页面调用时使用) public function filters() { return array( 'accessControl', // perform access control for CRUD operations 'postOnly + delete', // we only allow deletion via POST

  • Yii2设置默认控制器的两种方法

    本文主要给大家介绍了关于Yii2默认控制器设置的内容,分享了两种方法供大家参考学习,下面来一起看看详细的介绍: 方法1: 首先Yii2中在/vendor/yiisoft/yii2/web/Application.php的28行 class Application extends \yii\base\Application { /** * @var string the default route of this application. Defaults to 'site'. */ public

  • yii2控制器Controller Ajax操作示例

    本文实例讲述了yii2控制器Controller Ajax操作的方法.分享给大家供大家参考,具体如下: public function actionSample() { if (Yii::$app->request->isAjax) { $data = Yii::$app->request->post(); $searchname= explode(":", $data['searchname']); $searchby= explode(":&quo

  • Yii2创建控制器(createController)方法详解

    本文实例讲述了Yii2创建控制器(createController)方法.分享给大家供大家参考,具体如下: yii中创建控制器的是在application中的request通过UrlManager解析得出路由信息的,然后再由yii\base\Module中的 public function runAction($route, $params = []) 方法来创建控制器,最后由控制器再执行相应的动作. 首先得明确,Yii中的路由分三种情况: 第一种是带有模块的(module id/control

  • Python实现创建模块的方法详解

    目录 楔子 __import__ importlib.machinery 通过 module 类创建模块 将一个类的实例变成一个模块 小结 楔子 导入一个模块,我们一般都会使用 import 关键字,但有些场景下 import 难以满足我们的需要.所以除了 import 之外还有很多其它导入模块的方式,下面就来介绍一下. __import__ 这是一个内置函数,解释器在 import 的时候,实际上就执行了这个函数. # import os 等价于如下方式 os = __import__("os

  • vue自定义过滤器创建和使用方法详解

    本文实例为大家分享了vue自定义过滤器创建和使用方法,供大家参考,具体内容如下 过滤器:生活中有很多例子,净水器 空气净化器 . 过滤器的作用:实现数据的筛选.过滤.格式化. vue1.*版本是有内置的过滤器,但是在vue2.*所有的版本都已经没有自带的过滤器了. 1.过滤器创建 过滤器的本质 是一个有参数 有返回值的方法 new Vue({ filters:{ myCurrency:function(myInput){ return 处理后的数据 } } }) 2.过滤器使用 语法: <any

  • eclipse 如何创建 user library 方法详解

    eclipse 创建 user library 方法 1.Window - Preferences - Java - Build Path - User Libraries 2.新建 UserLibraries 3. 4.重复上一步依次添加需要的jar文件 5.添加完毕,点击OK. 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

  • Android开发教程之Fragment定义、创建与使用方法详解【包含Activity通讯,事务执行等】

    本文实例讲述了Android开发教程之Fragment定义.创建与使用方法.分享给大家供大家参考,具体如下: 概述 Fragment是activity的界面中的一部分或一种行为.你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment.你可以把Fragment认为模块化的一段activity,它具有自己的生命周期,接收它自己的事件,并可以在activity运行时被添加或删除. Fragment不能独立存在,它必须嵌入到

  • Laravel框架创建路由的方法详解

    本文实例讲述了Laravel框架创建路由的方法.分享给大家供大家参考,具体如下: 我这里使用的Laravel版本是5.6,路由位置在routes/web.php中,所以我们在这个文件中添加我们想要添加的路由. 1.基础路由 //get请求,结果如下图 Route::get('basic1',function (){ return 'Hello World'; }); //post请求,这里不展示结果图 Route::post('basic2',function (){ return 'Post'

  • python进程的状态、创建及使用方法详解

    本文实例讲述了python进程的状态.创建及使用方法.分享给大家供大家参考,具体如下: 进程以及状态 1. 进程 程序:例如xxx.py这是程序,是一个静态的 进程:一个程序运行起来后,代码+用到的资源 称之为进程,它是操作系统分配资源的基本单元. 不仅可以通过线程完成多任务,进程也是可以的 2. 进程的状态 工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态 就绪态:运行的条件都已经慢去,正在等在cpu执行 执行态:cpu

  • Android BottomNavigationBar底部导航控制器使用方法详解

    最近Google在自己推出的Material design中增加了Bottom Navigation导航控制.Android一直没有官方的导航控制器,自己实现确实是五花八门,有了这个规定之后,就类似苹果的底部Toolbar,以后我们的APP就会有一致的风格,先看一张效果: 这是官方在Material design中给出一张图,确实很不错. 1.BottomNavigationBar的下载地址 https://github.com/Ashok-Varma/BottomNavigation 2.使用

  • python原类、类的创建过程与方法详解

    今天为大家介绍一下python中与class 相关的知识-- 获取对象的类名 python是一门面向对象的语言,对于一切接对象的python来说,咱们有必要深入的学习与了解一些知识 首先大家都知道,要获取一个对象所对应的类,需要使用class来进行检索. 但如果我们只是一个简单的赋值语句,能这么使用么?让我们看下下面的代码: num=10 string='abc' class MainClass: pass p=MainClass() print(num.__class__) # output:

  • JavaScript创建数组的方法详解

    目录 JavaScript创建数组 数组的使用 将数组转换为分割字符串 数组中新增元素 筛选数组 删除数组指定元素 总结 JavaScript创建数组 1.利用new创建数组 var arr = new Array();//创建了一个空数组 2.利用数组字面量创建数组(比较常用) 字面量:一种固定值的表示方法 一看就知道什么数据类型,比如8一看就是数字类型 //1.利用数组字面量(是方括号)创建数组 var arr = [];//创建了一个空数组 var arr1 = [1,2,'student

随机推荐