从路由到调控器,从布局文件的角度去掌握Yii2

Yii2是贰个新奇的框架,其捐躯了前天流行的解耦设计,用三个可观耦合的构造提需要开辟者八个福利的几类华而不实,Application,Module,Component,乃至是瑟维斯Locator.想让对象具备哪一种特征就直接接轨相应的目的,想要改换她就去复写父类的格局,固然不相符开放密闭原则,单一职分标准,李氏替换原则等面向对象设计原则,但确实很方便.

此前的稿子澄清了二回呼吁的上马到截至。重要讲了Yii Applicaton实例的创造、起头化,UrlManager怎么样重返Yii中的路由新闻,到runAction,最终将Response发送给顾客端。那之中略过了runAction到底是怎么找到以及调用对应的调节器中的方法的,下边继续从源码动手。

缘起

因为一个月的短命停留,作者在给心上人搞专业,所以Yii体系的稿子推延了很短日子,以后又重拾当时的学识,给公众好好撸下这一连串的博客

提起Yii,虽然是海外的开荒者搞的,不过它的小编是中原人,这才是让我们引以为豪的,如若之后有空子薛强回国民代表大会力发展PHP职业,作者自然回来他麾下搞职业,为PHP在境内的进化贡献本人的一份力,纵然未来从未那么些力量,那不薛强没回来嘛,回来的话那时的自己决然能够的~哈哈哈~

领英上强哥的背景如下:

岗位:MicroStrategy 公司担任构架师

地址:美利坚同盟国都城Washington Metro Area

教育:

  • Duke大学·Computer科学·博士
  • 山西高校·Computer科学·大学生

强哥是村生泊长的华夏族,在U.S.有定点专职工作,希腊语很好,同期粤语一点难题都并未有!!

好了,话步前言,上节我们早已将Yii2.0一体化的装置到大家的机械中啦,在浏览器中输入下边的地方,你就足以访问你的服务器应用啦~

http://服务器IP/app/yii/web/index.php

出现下边包车型客车授命那就对呀~

图片 1

事先的稿子辟谣了三遍呼吁的开始到竣工。重要讲了Yii Applicaton实例的开创、最早化,UrlManager怎么样再次回到Yii中的路由消息,到runAction,最后将Response发送给客户端。这里面略过了runAction($route)到底是如何找到以及调用相应的调节器中的方法的,上面继续从源码入手。

本文就从Yii2 Advance版本的布局文件入手,详细介绍配置文件角度的Yii2框架,其中提到到的部分水源方面包车型客车要点就要此起彼落文章中种种表达.

1、承袭关系

第一大家弄清楚Yii多少个首要类的接续关系:

  • yiiwebApplication extends yiibaseApplication
  • yiibaseApplication extends yiibaseModule
  • yiibaseModule extends yiidiServiceLocator
  • yiidiServiceLocator extends yiibaseComponent
  • yiibaseComponent extends yiibaseObject

总体布局

图片 2

assets文件夹:assets的法力是便于模块化,插件化的,一般的话出于安全原因不相同意通过url访谈protected下边包车型大巴文件 ,可是我们又希望将module单独出来,所以要求利用公布,将要一个目录下的文本复制一份到assets上面方便通过url访问。

commands文件夹:调控台脚本贮存的地点,自动运营脚本

config文件夹:配置文件寄存的文本夹

controller文件夹:MVC中C文件存放的文书夹

mail文件夹:邮件发送目录,具体干啥的自身还在物色中哈~

models文件夹:MVC中M文件存放的公文夹

runtime:日志文件

tests:测量试验脚本文件夹

vendor:第三方组件贮存,composer下载的组件存放的公文夹,自动帮您autoload

views:MVC中V寄存的文本夹

web:web主应用入口脚本贮存的职位

上述是整整文件夹的布局,里面包车型地铁逐条文件有何用,小编会在继续的【应用Yii2.0搭建后台应用框架】中详细介绍

本身这一名目好些个的文章均出自于Yii中文网中对Yii2.0的高尚指南,谢谢国内开垦者对社区的孝敬,多谢翻译的人,让大家免去了百度翻译之苦。

要是咱们不太喜欢本身的叙述,能够去看一下合法对Yii2.0的演说,很详细,但很官方,不会调戏你^_^

法定文书档案【中文版】:

Yii 应用参照模型-视图-调节器 (MVC)设计方式来公司。不懂MVC?这么说吗,不管是前者选择还是后端应用,首当其冲的设计方式就是MVC。所以领会它十分有要求!

M模型代表数量、业务逻辑和法规;V视图展现模型的出口;C调整器接受出入并将其转移为模型和视图命令。

图片 3

那就是Yii的全方位架构划设想计,大家的MVC正是里面的调整器,视图和模型,他们的分级职能方面也讲了下,一般的后端应用,M表示从数据库、第三方链接、本三步跳件中获得的数码开展管理,整理,在付出到V端,V端的效率一般是在页面中反映给用户的页面,假设是以数量的款型重回给客商,这那么些V层就不用做过多的渲染。C层的话首假设连接两个的功用,C层获取到客户的央求,传给M层,M层管理好数据,反馈给C层,C层再将数据给到V层,V层突显给客商。MVC模型的方便之处正是逻辑清晰,各类模块担任和睦的事,井井有理,非常便于初大家领悟,是多个入门的模型。

除开,Yii还蕴藏其余逻辑管理块,举个例子说下边图中的入口脚本【调用应用一方始必被调用的台本文件】,应用中央【Yii::$app全局可访问对象】,应用组件【全局通用的局地工具集】,模块【业务逻辑单元,每种专业逻辑二个模块,会让代码很清晰】,过滤器【标准作为的指标,在调节器实行在此以前或今后调用,定义一类特别的表现】,前端财富和小部件我们先不讲,因为是涉嫌到前端的部分组件内容,后边作者会单独开垦一个类别来说前端知识,我出这一文山会海的指标关键是针对后台应用~

1、承接关系

先是大家弄清楚Yii多少个重大类的三翻五次关系:

  • yiiwebApplication extends yiibaseApplication
  • yiibaseApplication extends yiibaseModule
  • yiibaseModule extends yiidiServiceLocator
  • yiidiServiceLocator extends yiibaseComponent
  • yiibaseComponent extends yiibaseObject

Yii2的安插文件分两级:

2、从runAction继续

找到yiiwebApplication的handleRequest方法,这里对runAction实行了调用:

list ($route, $params) = $request->resolve();$result = $this->runAction($route, $params);

runAction的概念位于父类的父类yiibaseModule中,这里曾经获得到的音讯为:通过yiiwebRequest对近些日子url央浼的分析,重临的一个路由。这些路由$route的格式为site/index 这种样式的,大概为附加模块新闻Metting/attender/index 这种情势的。

//yiibaseModulepublic function runAction($route, $params = []){    $parts = $this->createController;    if (is_array {        /* @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) . '".');    }}

能够看到,runAction的第二个操作便是基于$route创制controller实例。

进口脚本

周详的敌人或然已经开掘了,为何大家在上面包车型地铁看望链接中前边有个index.php,对,正是它,它便是进口脚本,每便web乞求都不能够不透过它!

http://172.16.122.58/app/yii/web/index.php

一般他都以在web这些目录下边包车型的士,这些是web应用的输入脚本。

图片 4

还大概有个输入脚本是什么呢,调控台脚本,上面包车型地铁不得了叫yii的php脚本,啥成效吧,你们思索啊,电商后台南,假使有相当多人要调度仓库储存,是还是不是调动一回就给改一遍啊,确定不会呀,库存操作如果调用数据库太频繁了,数据库肯定扛不住的,我们的做法正是先放置类似于Redis的缓存中,等到一定量的时候,或然有个1秒钟的时候大家给同步一次数据库,同步的措施就是调用调整台脚本啦,同盟Linux的crontab,完美化解数据库调用过于频仍的难点。调节台脚本后边大家会介绍,一般业务线中用的还挺多的。

输入脚本首要成就以下专门的职业:

  • 概念全局常量;
  • 挂号 Composer 自动加载器;
  • 包含 Yii 类文件;
  • 加载应用配置;
  • 创设一个接纳实例并配备;
  • 调用 yiibaseApplication::run() 来管理须求。

    // comment out the following two lines when deployed to production defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev');

    require(DIR . '/../vendor/autoload.php'); require(DIR . '/../vendor/yiisoft/yii2/Yii.php');

    $config = require(DIR . '/../config/web.php');

    (new yiiwebApplication($config))->run();

入口脚本是概念全局常量的最佳地点,话虽如此,不提出在这里定义啥全局变量!Yii 援助以下八个常量:

YII_DEBUG:标志应用是不是运转在调节和测量检验情势。当在调节和测验格局下,应用会保留更加多日志消息,假如抛出非常,会显得详细的失实调用旅馆。由此,调节和测量检验形式首要适合在开辟阶段使用,YII_DEBUG 暗中认可值为 false。

YII_ENV:标志应用运行的条件。YII_ENV 暗中同意值为 'prod',表示应用运维在线上产品情状。

YII_ENABLE_ERROR_HANDLER:标记是或不是启用 Yii 提供的错误处理,默许为true。

autoload.php,读过自家从前文章的爱侣一定对她有印象,PSEvoque-4,自动加载器哈,那几个是登记composer自动加载器的。

Yii.php,包括Yii类的文本路线。

尾数第二行是加载应用配置。最终一行是运转贰个采纳,那个中的$config【web.php】那几个文件会在末端详细解答。

2、从runAction继续

找到yiiwebApplication的handleRequest方法,这里对runAction进行了调用:

list ($route, $params) = $request->resolve();
$result = $this->runAction($route, $params);

runAction的定义位于父类的父类yiibaseModule中,这里一度拿到到的消息为:通过yiiwebRequest对当下url央求的剖判,重回的三个路由。那几个路由$route的格式为site/index 这种格局的,大概为附加模块消息Metting/attender/index 这种样式的。

//yiibaseModule
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) . '".');
    }
}

能够看出,runAction的第二个操作正是基于$route创制controller实例。

  1. common级别
  2. 站点品级

3、创设controller实例对象

这几个方法最后的目标正是成立贰个调整器实例对象,要么是controllers中的一个调节器,要么是modules的controllers中的贰个调控器。

createController的讲解也写的比较掌握,一共针对4种情状做拍卖:

  1. 设若$route为空,那么直接运用defaultRoute,能够见见defaultRoute在yiiwebApplication中定义,暗中同意值为site
  2. 假如$route的第四盘部($id)相配到了作者们config/main.php modules中的某一项,那么会选择路由的剩余部分($route)作为参数递归调用createController
  3. 只要controllerMap中窥见了以第一有的($id)为key的项,那么会事先遵照controllerMap中的配置来创立controller实例
  4. 因为模块能够无限的嵌套下去,yii2会递归的调用createController来成立实例

首先说一下主意中$route的拍卖,除去两侧的斜线/,对$route中是还是不是留存双斜线进展判断,然后正是将$route按照/分为第一片段$id和第二某些,新的$route

public function createController{    if (strpos($route, '/') !== false) {        //将Metting/attender/index分为 $id='Metting'; $route='attender/index'        list ($id, $route) = explode('/', $route, 2);    } else {        $id = $route;        $route = '';    }    //这里就是上面说的controllerMap和模块会优先进行处理    // 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;    if ($module !== null) {        return $module->createController;    }    //下面代码暂时省略}

controllerMap表达:有的时候大家定义的路由也许不想跟调控器名一致,举个例子引进了第三方的库,这里边的主宰器名你没法改动。而controllerMap是二个可配置项,在您的安顿文件中能够自定义

一经controllerMap中海市蜃楼此id为key的项,那么这么些id(譬如Metting)会作为module来举行获取:$module = $this->getModule;看getModule怎么着管理:

//yiibaseModulepublic function getModule($id, $load = true){    //先不看子module的情况    if (($pos = strpos) !== false) {        // sub-module        $module = $this->getModule(substr($id, 0, $pos));        return $module === null ? null : $module->getModule(substr($id, $pos   1), $load);    }    //这里是$id这个模块是否存在的判断逻辑    //如果在_modules中找到了这个元素并且是Module的实例,那么直接返回    //否则根据配置信息创建对象并返回    if (isset($this->_modules[$id])) {        if ($this->_modules[$id] instanceof Module) {            return $this->_modules[$id];        } elseif  {            Yii::trace("Loading module: $id", __METHOD__);            /* @var $module Module */            $module = Yii::createObject($this->_modules[$id], [$id, $this]);            $module->setInstance;            return $this->_modules[$id] = $module;        }    }    return null;}

此处大家对$_modules这么些成员变量进行打字与印刷,能够看来结果正是大家在config/main.php中的modules那个数组中的配置:

//config/main.php'modules' => [    'Metting' => [         'class' => 'backendmodulesMettingModule',     ],]

进而,当找到那几个module后,便是依据大家config的这一个新闻来实例化二个Module,比如上面包车型地铁Metting/attender/index的例子:

  • 调用 $module = getModule('Metting')
  • 返回backendmodulesMettingModule的实例
  • 然后$module->createController('attender/index')

此地是递归的调用,仍然会检讨attender是或不是是一个module,重返null,继续实行createController上面包车型客车代码:

//yiibaseModule createController 代码简化$controller = $this->createControllerByID;if ($controller === null && $route !== '') {    $controller = $this->createControllerByID($id . '/' . $route);    $route = '';}return $controller === null ? false : [$controller, $route];

createControllerByID的操作就比较轻易了,首要:

  • 自己商量传过来的那一个controller id是不是合法,满意/^[a-z][a-z0-9\-_]*$/
  • 连字符转为大写,拼接命名空间(controllerNamespace)消息,拼接'Controller'后缀
  • 调用Yii::createObject创建调节器对象

至于controllerNamespace,如若访谈的不是模块,那么使用的正是暗中认可的命名空间,即我们在config/main.php中布局的值,如:backendcontrollers。纵然是模块,$module是大家协调写的Module.php, 它再而三了yiibaseModule,何况评释了controllerNamespace,如:

//backendmodulesMettingModule.phppublic $controllerNamespace = 'backendmodulesMettingcontrollers';

故而能够见见createController,模块与非模块controller实例的创导,指标是找到正确的命名空间下的调控器。

最终createController返回[控制器实例, action名]

留存三个主题素材并没有证实的是$_modules内部的数据是什么日期以及如何初步化的?见上面:5、$_modules开首化表达。

使用宗旨布局

利用大目的在于输入脚本中创立并能通过发布式 Yii::$app 全局范围内访谈。访谈的变量定义在哪个地方呢,由于应用中央布局比较复杂,就是刚刚提到的$config,config文件夹中的web.php文件。前面比较复杂的配置都能够放置单个文件中,这是个手艺,即收缩了安顿文件的代码行数,也将一切框架清晰非常多。

图片 5

其一里面定义了相当的多属性,大家来分别看下吧。

<?php

$params = require(__DIR__ . '/params.php');

$config = [

params那一个参数里的保有变量就被定义在params.php这几个文件之中。

上面是本人的档案的次序中安插的有些文本在上边定义

<?php

$params = require(__DIR__ . '/params.php');
$rules = require(__DIR__ . '/rules.php');
$aliases = require(__DIR__ . '/aliases.php');
$cacheConfig = require(__DIR__ . '/cache.php');

那在那之中主假若params参数,rules路由法则,aliases外号法规,cacheConfig缓存配置,你恐怕会存疑,为什么db这么首要的未有布置上来,db是分别碰着的,在index.php中会区分stable境况、pro境况依然测量试验情形做区分。

大家依然回到大家的Yii源码,配置文件上面配置了params所在的公文,

$config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'components' => [
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'A9BMCrvbxuCEnE39rVpOUECgcBJTnzUH',
        ],
        'cache' => [
            'class' => 'yiicachingFileCache',
        ],
        'user' => [
            'identityClass' => 'appmodelsUser',
            'enableAutoLogin' => true,
        ],
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
        'mailer' => [
            'class' => 'yiiswiftmailerMailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yiilogFileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'db' => require(__DIR__ . '/db.php'),
        /*
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
            ],
        ],
        */
    ],
    'params' => $params,
];

那边有几本性子,id、basePath、bootstrap和components。别的还应该有多少个非常主要的性质:aliases、language、modules。

3、创造controller实例对象

其一法子最终的指标便是开创三个控制器实例对象,要么是controllers中的贰个调整器,要么是modules的controllers中的多个调节器。

createController的笺注也写的可比清楚,一共针对4种境况做拍卖:

  1. 例如$route为空,那么直接运用defaultRoute,能够见见defaultRoute在yiiwebApplication中定义,默许值为site
  2. 只要$route的率先部分($id)相称到了我们config/main.php modules中的某一项,那么会动用路由的盈余部分($route)作为参数递归调用createController($route)
  3. 假定controllerMap中开采了以率先局地($id)为key的项,那么会优先遵照controllerMap中的配置来成立controller实例
  4. 因为模块能够Infiniti的嵌套下去,yii2会递归的调用createController来创制实例

第一说一下主意中$route的拍卖,除去两边的斜线/,对$route中是或不是留存双斜线拓展判别,然后便是将$route按照/分为第一有些$id和第二有的,新的$route

public function createController($route)
{
    if (strpos($route, '/') !== false) {
        //将Metting/attender/index分为 $id='Metting'; $route='attender/index'
        list ($id, $route) = explode('/', $route, 2);
    } else {
        $id = $route;
        $route = '';
    }
    //这里就是上面说的controllerMap和模块会优先进行处理
    // 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);
    }
    //下面代码暂时省略
}

【注】controllerMap表明:不经常大家定义的路由大概不想跟调节器名一致,比方引进了第三方的库,那里边的操纵器名你未曾艺术改动。而controllerMap是三个可安顿项,在你的布署文件中能够自定义

假定controllerMap中不设有此id为key的项,那么那些id(譬喻Metting)会作为module来开展获取:$module = $this->getModule($id);看getModule怎样管理:

//yiibaseModule
public function getModule($id, $load = true)
{
    //先不看子module的情况
    if (($pos = strpos($id, '/')) !== false) {
        // sub-module
        $module = $this->getModule(substr($id, 0, $pos));

        return $module === null ? null : $module->getModule(substr($id, $pos   1), $load);
    }
    //这里是$id(Metting)这个模块是否存在的判断逻辑
    //如果在_modules中找到了这个元素并且是Module的实例,那么直接返回
    //否则根据配置信息创建对象并返回
    if (isset($this->_modules[$id])) {
        if ($this->_modules[$id] instanceof Module) {
            return $this->_modules[$id];
        } elseif ($load) {
            Yii::trace("Loading module: $id", __METHOD__);
            /* @var $module Module */
            $module = Yii::createObject($this->_modules[$id], [$id, $this]);
            $module->setInstance($module);
            return $this->_modules[$id] = $module;
        }
    }

    return null;
}

此地大家对$_modules那几个成员变量实行打印,能够看看结果正是我们在config/main.php中的modules那个数组中的配置:

//config/main.php
'modules' => [
    'Metting' => [
         'class' => 'backendmodulesMettingModule',
     ],
]

由此,当找到那一个module后,就是依照大家config的那几个音信来实例化多个Module,例如上面包车型大巴Metting/attender/index的例证:

  • 调用 $module = getModule('Metting')
  • 返回backendmodulesMettingModule的实例
  • 然后$module->createController('attender/index')

这里是递归的调用,依旧会检查attender是不是是叁个module,再次来到null,继续试行createController下边包车型地铁代码:

//yiibaseModule createController($route) 代码简化
$controller = $this->createControllerByID($id);
if ($controller === null && $route !== '') {
    $controller = $this->createControllerByID($id . '/' . $route);
    $route = '';
}
return $controller === null ? false : [$controller, $route];

createControllerByID的操作就相比轻巧了,重要:

  • 自作者商议传过来的那些controller id是或不是合法,满意/^[a-z][a-z0-9\-_]*$/
  • 连字符(-)转为大写,拼接命名空间(controllerNamespace)音信,拼接'Controller'后缀
  • 调用Yii::createObject创设调整器对象

关于controllerNamespace,倘诺访谈的不是模块,那么使用的正是暗中同意的命名空间,即我们在config/main.php中配备的值,如:backendcontrollers。固然是模块,$module是大家和好写的Module.php, 它继续了yiibaseModule,而且表明了controllerNamespace,如:

//backendmodulesMettingModule.php
public $controllerNamespace = 'backendmodulesMettingcontrollers';

故此能够见到createController,模块与非模块controller实例的开创,指标是找到科学的命名空间下的调控器。

最终createController返回[控制器实例, action名]

【疑问】存在三个难点远非证实的是$_modules中间的数目是哪天以及哪些起头化的?见上边:5、$_modules初始化表明。

common看名称就会想到其意义,通用的布局文件.站点等级会复写common等级的布署,作用域也是站点.

4、run controller action

上面大家见到,已经依照路由找到并创制了controller实例对象,接下里的操作就是回去Module中的runAction继续施行,调用调整器里面包车型客车action了

//yiibaseModule runAction$result = $controller->runAction($actionID,$params);

因为兼具的controller类都接二连三了yiiwebController,所以大家到此地找到runAction方法,位于其父类yiibaseController中,通过源码能够看出这几个runAction首要施行了:

  • 依照actionID成立二个InlineAction对象,内部是经过反射推断了这几个办法是不是存在,InlineActoin对象保存了现阶段的controller对象以及actionMethod新闻
  • 实施生命周期函数$module->beforeAction
  • beforeAction实施实现调用$result = $action->runWithParams
  • 举办生命周期函数$model->afterAction

$action->runWithParams就相比较轻易了,就是接纳了笔者们事先封存在InlineAction对象中的新闻,实施call_user_func_array([$this->controller, $this->actionMethod], $args);

从这之后,怎样从url 到 Yii路由 到 controller 到 action的流水生产线就解析理解了。

路由到调整器施行流程图
图片 6

id

yiibaseApplication::id 属性用来区分别的应用的天下无双标记ID。一般布置为顺序名称。要求属性之一。

4、run controller action

地方大家见到,已经依据路由找到并创造了controller实例对象,接下里的操作正是回去Module中的runAction继续实践,调用调控器里面包车型客车action了

//yiibaseModule runAction
$result = $controller->runAction($actionID,$params);

因为兼具的controller类都承继了yiiwebController,所以我们到此处找到runAction方法,位于其父类yiibaseController中,通过源码能够见到那一个runAction首要实践了:

  • 基于actionID创设两个InlineAction对象,内部是因而反射决断了这几个主意是或不是存在,InlineActoin对象保存了现阶段的controller对象以及actionMethod音信
  • 实行生命周期函数$module->beforeAction($action)
  • beforeAction推行达成调用$result = $action->runWithParams($params)
  • 举办生命周期函数$model->afterAction($action)

$action->runWithParams($params)就比较简单了,就是选取了我们事先封存在InlineAction对象中的音讯,执行call_user_func_array([$this->controller, $this->actionMethod], $args);

从这之后,怎么着从url 到 Yii路由 到 controller 到 action的流水生产线就深入分析理解了。

【附】路由到调控器推行流程图
图片 7

鉴于Yii2为了简化开辟难度,所以顾客定义的目录加载格局全体用到Yii2本身定义的autoload方法(Yii.php中注册的BaseYii.php中的autoload),并非编写composer.json然后dump autoload.

5、$_modules最初化表达

透过在此以前的Application的构造方法,以及init方法只是伊始化了bootstrap、extension以及core components等,丝毫一向不布署文件中module的初步化印迹。然后当心到yiibaseApplication中的构造方法的末段还大概有一句:Component::__construct,正是又积极的调用了Component的构造方法,事实上Component本身从未落实构造方法而是继续自她的父类:yiibaseObject

public function __construct($config = []){    if (!empty {        Yii::configure($this, $config);    }    $this->init();}

主要在那个Yii::configure($this, $config),其实configure的操作很简短,正是遍历$config数组,以key作为指标的分子属性,对应的value作为质量的值举办早先化操作,这里的$this此时即使yiiwebApplication对象了。

//yiiBaseYiipublic static function configure($object, $properties){    foreach ($properties as $name => $value) {        $object->$name = $value;    }    return $object;}

以地点我们讲的config中的modules为例,那正是:

$object->modules = [    'Metting' => [         'class' => 'backendmodulesMettingModule',     ],]

而是大家找遍全部类以及继续的类,都未有找到$modules本条本性,那Yii是如何是好的吗?其实就是运用了PHP的魔术点子,展开yiibaseComponent,能够观望yii2定义了__set __get __call __isset等常用的魔术点子,在性质赋值的时候,大家知晓,倘使属性不设有会实践__set($name,$value).

public function __set($name, $value){    $setter = 'set' . $name;    if (method_exists($this, $setter)) {        // set property        $this->$setter;        return;    }     //下面的代码暂时省略}

传说代码大家知道,要对那几个属性起始化,那么快要兑现相应的setter方法,对于modules来讲正是setmodules,由于PHP函数名,方法名,类名不区分轻重缓急写,所以找到了坐落yiiwebModule中的:

public function setModules{    foreach ($modules as $id => $module) {        $this->_modules[$id] = $module;    }}

终于,找了了$_modules中值得由来。

basePath

yiibaseApplication::basePath 钦定该采用的根目录。系统预订义 @app 代表那个路子。 你借使须求require目录内的文书,能够应用这几个法子找到呼应文件。其他两个要求属性,那么些是必得得配置的。

5、$_modules开首化表明

通过事先的Application的构造方法,以及init方法只是最先化了bootstrap、extension以及core components等,丝毫向来不配备文件中module的初叶化印迹。然后小心到yiibaseApplication中的构造方法的终极还会有一句:Component::__construct($config),正是又主动的调用了Component的构造方法,事实上Component本人从不兑现构造方法而是继续自他的父类:yiibaseObject

public function __construct($config = [])
{
    if (!empty($config)) {
        Yii::configure($this, $config);
    }
    $this->init();
}

根本在那几个Yii::configure($this, $config),其实configure的操作很简短,就是遍历$config数组,以key作为目的的分子属性,对应的value作为质量的值进行开始化操作,这里的$this此时固然yiiwebApplication对象了。

//yiiBaseYii
public static function configure($object, $properties)
{
    foreach ($properties as $name => $value) {
        $object->$name = $value;
    }
    return $object;
}

以地点大家讲的config中的modules为例,那就是:

$object->modules = [
    'Metting' => [
         'class' => 'backendmodulesMettingModule',
     ],
]

而是大家找遍整个类以及后续的类,都尚未找到$modules以此天性,那Yii是如何做的啊?其实就是运用了PHP的魔术点子,打开yiibaseComponent,能够观察yii2定义了__set __get __call __isset等常用的魔术点子,在质量赋值的时候,我们知晓,若是属性海市蜃楼会实施__set($name,$value).

public function __set($name, $value)
{
    $setter = 'set' . $name;
    if (method_exists($this, $setter)) {
        // set property
        $this->$setter($value);
        return;
    } 
    //下面的代码暂时省略
}

基于代码我们知道,要对那么些属性开端化,那么将在兑现相应的setter方法,对于modules来讲就是setmodules,由于PHP函数名,方法名,类名不区分轻重缓急写,所以找到了坐落yiiwebModule中的:

public function setModules($modules)
{
    foreach ($modules as $id => $module) {
        $this->_modules[$id] = $module;
    }
}

终于,找了了$_modules中值得由来。

用法是将具备路径在index.php中全部注册到全局容器Yii中.方法就是Yii::setAlias();方法.

bootstrap

本条性格很实用,它同意你用数组钦命运营阶段yiibaseApplication::bootstrap()须求周转的零部件。一般后端应用中安顿个

    'bootstrap' => ['log'],

即可。

编排的位置就明确在这几个bootstrap.php文件中,但这些等第实际不是Yii的bootstrap阶段,只是在index.php中触发.有歧义,需求注意.

components

这是最关键的习性,它同意你注册多个在别的地方选拔的选择组件。比如说session、log、db和cache啊,都在这中间配备的,具体的下一节接纳组件中会讲到。

在common等级中,设置的是站点的root.在site中安装的是module的root.

aliases

该属性允许你用二个数组定义多少个外号。数组的key为外号名称,值为对应的渠道。

[
    'aliases' => [
        '@name1' => 'path/to/path1',
        '@name2' => 'path/to/path2',
    ],
]

自身的布署内部都是设置的extension扩张类的别称,extension里面放置一些基础调用类,比如说CU奇骏L、微信支付等等的。

[
    '@ext' => dirname(__DIR__) . '/extensions',
]

main里面有相当多的装置项.

language

该属性内定应用体现给终端顾客的言语,默以为 en 标志意大利语。假如急需事先其余语言能够配备该属性。

    'language' => 'zh-CN',

0. 'params'

率先require全体包罗common和本站点的全套params.php(params-loacl.php),并将重临值放在params键下.

modules

该属性钦命应用所蕴藏的模块。还记得上面说的事情的分开吗,是的,正是在modules里面实行分割的,对应的目录便是根目录下的modules目录,也是索要布署哒~

[
    'modules' => [
        // "booking" 模块以及对应的类
        'booking' => 'appmodulesbookingBookingModule',

        // "comment" 模块以及对应的配置数组
        'comment' => [
            'class' => 'appmodulescommentCommentModule',
            'db' => 'db',
        ],
    ],
]

自己的模块的撤销合并

'modules' => [
        'admin' => [
            'class' => 'appmodulesadminAdmin',
        ],
        'api' => [
            'class' => 'appmodulesapiApi',
        ],
        'user' => [
            'class' => 'appmodulesuserUser',
        ],
        'bus' => [
            'class' => 'appmodulesbusBus',
        ],
        'goods' => [
            'class' => 'appmodulesgoodsGoods',
        ],...
]

本条布局对你代码的结构清晰性有非常大的升官,后端应用必配属性。

1. 'id'

哪怕当下站点的称谓

defaultRoute

该属性钦命未安插的呼吁的响应 路由法则,路由准绳大概包罗模块ID,调整器ID,动作ID。 比方helppost/createadmin/post/create,假如动作ID未有一点名,会动用yiibaseController::defaultAction中钦赐的暗中同意值。

对于 yiiwebApplication 网页应用,暗许值为 'site' 对应 SiteController 调控器,并动用暗中同意的动作。

对于 yiiconsoleApplication 调整台应用, 私下认可值为 'help' 对应 yiiconsolecontrollersHelpController::actionIndex()。

说完了基础的着体贴布局,别的的基本点布局能够去官方文书档案中查阅哟,这里边很详细,可是作者要么针对作者动用过的和我们谈天说地。

咱俩来看下components组件配置有哪些重大的配备。

2. 'basePath'

看名就会知道意思,站点根目录

选拔组件

利用宗旨布局落成,大家来探视里面components有怎么着重大配置吧

在同叁个选用中,每种应用组件都有一个无出其右的 ID 用来差别其余使用组件,你能够经过如下表明式访谈应用组件

Yii::$app->componentID

官方网址给出的components示例如下

[
    'components' => [
        // 使用类名注册 "cache" 组件
        'cache' => 'yiicachingApcCache',

        // 使用配置数组注册 "db" 组件
        'db' => [
            'class' => 'yiidbConnection',
            'dsn' => 'mysql:host=localhost;dbname=demo',
            'username' => 'root',
            'password' => '',
        ],

        // 使用函数注册"search" 组件
        'search' => function () {
            return new appcomponentsSolrService;
        },
    ],
]

此间定义了三个布局属性:cache、db、search,除了那些之外,相比较关键的components属性还有如下多少个:urlManager、user、session、errorHandler和log。

3. 'controllerNamespace'

站点下controller的命名空间,在MVC阶段,Yii2.0会依附这一个特性结合路由自动生成controller的命名空间.module等第的controller中controllerNamespace须要再行定义,能够在Module.php的init()方法中一直赋值.

cache

代表代表各样缓存存款和储蓄器,例如内部存款和储蓄器,文件,数据库。具体会在【Yii种类】操作缓存一章中等教育授

4. 'bootstrap'

本条布局有一些看头,和bootstrap.php不相同,这几个才是的确意义于bootstrap阶段的概念,方法正是在中间写入你必要在bootstrap阶段响应的module大概component乃至是别的对象.

响应什么吧?有三种情状,要是您的module只怕component以致贰个默默的目的援用了yiibaseBootstrapInterface接口,并促成了bootstrap()方法.将直接调用那么些方法.若无引用,那么单纯会实例化它,同一时候存入对象容器.

既然如此涉及bootstrap,这几个阶段Yii2还有大概会调用所用的extension,做上述一样的事情.假设你本人编写了关于Yii2的恢宏,那时候它将被实例化并缓存到Yii的靶子容器中.至于extension的编排,特别轻便,只需求为你的extension增多多个Yii2能用的bootstrap入口就可以(贰个目的,援引yiibaseBootstrapInterface接口,并将其布局在extension的安顿文件vendoryiisoftextensions.php中).

db

表示贰个方可推行数据库操作的数据库连接。具体会在【Yii连串】连接数据库一章中等教育授

5. 'modules'

对应的modules(譬如backend)目录下的Module对象的命名空间.方便Yii2踏向你所定义的module.

module在Yii第22中学是一组MVC的包裹,那一个概念或然在其余框架中不相同,譬喻laravel.

search

探求组件入口配置,以往有机缘和豪门唠唠solr相关,切割关键字,切割,切割~

6. 'component'

实质上那几个东西,在ZendFramework3.0中称之为module,是四个职能的贯彻,举个例子权限管理,路由管理,过滤器等等.

在Yii第22中学会对部分component内置好'class'字段的配备,约等于说,作为开荒职员,你没有供给通晓那一个component对应的对象在哪儿,直接配备后选择就足以了.当然若是协和写的话不可能不钦赐component的靶子入口.

component和module同样,和Yii2的上上下下运转流程联系特别致密,若是想详细驾驭,必需知道其运维流程,后续作品会详细表达.

component的布置如若想详细的询问,必得掌握驾驭Yii2的DI和对象模型,后续小说详细介绍.文章在此处

urlManager

支撑U福睿斯L地址分析和创立。具体会在【Yii类别】央浼处理一章中教授

7. '事件on ...'

本条有个别特别,可是丰裕好用,你可感到Application(注意,别的事件,举例MVC,由于实例不一致,这里的绑定对其低效)的暗许事件绑定callable,让其在相应的一代触发.Yii2的平地风波管理会单独开文表达.

Yii2的配置文件可能相对简单的,正如小编"易"的初衷,一切都以那么简单.

user

代表表明登入顾客音讯,仅在yiiwebApplication 网页应用中可用。假诺有后台客商权限认证管理,可去官方网址精晓明细。

session

意味着会话音信,仅在yiiwebApplication 网页应用中可用,我们一般都以透过这些来决定客商属性的,具体会在【Yii类别】诉求处理一章详细解说

errorHandler

拍卖 PHP 错误和特别

log

大局日志配置入口,具体会在【Yii体系】央浼管理一章批注

请谨严注册太多利用组件,应用组件就像全局变量,使用太多也许加大测量检验和护卫的难度。 一般景色下得以在急需时再创设当地组件。

我们能够重要关心多少个布局:db、urlManager、log和cache,这么些都以在经常职业中用的可比多的,必配的配备。

控制器

讲完了上边的配置文件,咱们再来看看组成Yii最最要紧的有的,也是我们工作经过中打交道最多的局地啦,请打起你们十一分的振作感奋,看好每二个字符哟~

率先我们来看下MVC中的C,下边大家就成他为Controller,因为他是进口,就和进口脚本同样,顾客发来呼吁,首先到的就是调整器(只是在后台应用中先到,即便是含有前端财富,客户率先接触到的终将是前面一个的代码哈)。

Controller的主要义务是接受客户央求,分发管理顾客诉求,拿到结果数据,递交给V层展示给客户。

继承yiibaseController类的指标

Controller由操作【action】组成,它是实行终端客户伏乞的最基础的单元,一个调控器可有一个或四个操作。

正如示例呈现富含多少个操作view 和 create 的调控器post

namespace appcontrollers;

use Yii;
use appmodelsPost;
use yiiwebController;
use yiiwebNotFoundHttpException;

class PostController extends Controller
{
    public function actionView($id)
    {
        $model = Post::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException;
        }

        return $this->render('view', [
            'model' => $model,
        ]);
    }

    public function actionCreate()
    {
        $model = new Post;

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }
}

客户访谈的时候即使直接被只想到某些action里面包车型客车,有其一action方法了,那么大家怎么样访谈它呢,那边就事关到叁个被称呼路由的东西。

极端客户通过所谓的【路由】寻觅到操作

路由使用如下格式:

ControllerID/ActionID

模块下的调节器,使用如下格式:

ModuleID/ControllerID/ActionID

一旦客户的央求地址为 http://hostname/index.php?r=site/index, 会执行site 调整器的index 操作。是的,有过web基础的相爱的人可能对这一个比较纯熟,?前面包车型大巴是参数,而这么些r参数就象征了寻访路径。

那正是说什么样去创立一个调整器呢?

在yiiwebApplication网页应用中,调节器应承接yiiwebController 或它的子类。

在yiiconsoleApplication调节台应用中,调整器承袭yiiconsoleController 或它的子类。

namespace appcontrollers;

use yiiwebController;

class SiteController extends Controller
{
}

site就为这一个Controller的调整器id。调节器ID平常是和财富有关的名词。

那些中有个事项需求留意下,Yii框架下都以经过驼峰命名法去找出对应的ID的,例如说那边的SiteController,在U宝马7系L调用中只需求保留site,后边的Controller无需安置url里面,调控器类必需能被自动加载。

调控器Id可蕴涵子目录前缀,比如 admin/article 代表 yiibaseApplication::controllerNamespace调节器命名空间下 admin子目录中 article 控制器。

上边为一些示范,即使yiibaseApplication::controllerNamespace调节器命名空间为 appcontrollers:

  • article 对应 appcontrollersArticleController;
  • post-comment 对应 appcontrollersPostCommentController;
  • admin/post-comment 对应 appcontrollersadminPostCommentController;
  • adminPanels/post-comment 对应 appcontrollersadminPanelsPostCommentController.

每一种应用有三个由yiibaseApplication::defaultRoute属性钦命的私下认可调整器; 正是大家地点讲的充裕

[
    'defaultRoute' => 'main'
]

当呼吁未有一点名路由,该属性值作为路由使用。

对于yiiwebApplication网页应用,它的值为 'site';

对于 yiiconsoleApplication调节台应用,它的值为 help。

所以URL为 http://hostname/index.php 表示由 site 调整器来管理。

创建action

创造action可粗略地在支配器类中定义所谓的操作方法来成功,操作方法必得是以action起来的公有方法。和controller,命名的时候是行使驼峰命名法,访谈的时候全小写,要是中间有三个大写字母,用'-'间隔即可。

namespace appcontrollers;

use yiiwebController;

class SiteController extends Controller
{
    public function actionIndex()
    {
        return $this->render('index');
    }

    public function actionHelloWorld()
    {
        return 'Hello World';
    }
}

独立操作大家不做查究,感兴趣的爱侣能够去研讨下yii自带的验证码模块源码。

图片 8

action的参数值从呼吁中猎取,

对于yiiwebApplication网页应用, 每一个操作参数的值从$_GET中获取,参数名作为键;一般不会动用$_GET直接去参数,那样不安全。一般接纳app的Request去收取顾客央浼的body和head。

$request = Yii::$app->request;

对于yiiconsoleApplication调节台应用, 操作参数对应命令行参数。

如下例,操作view (内联操作) 表明了多个参数 $id 和 $version

namespace appcontrollers;

use yiiwebController;

class PostController extends Controller
{
    public function actionView($id, $version = null)
    {
        // ...
    }
}

操作参数会被分歧的参数填入,如下所示:

  • http://hostname/index.php?r=post/view&id=123$id 会填入'123'$version 仍为 null 空因为未有version恳请参数;
  • http://hostname/index.php?r=post/view&id=123&version=2: $id$version分别填入'123''2'`;
  • http://hostname/index.php?r=post/view: 会抛出yiiwebBadRequestHttpException 十分因为央浼未有提供参数给必须赋值参数$id
  • http://hostname/index.php?r=post/view&id[]=123: 会抛出yiiwebBadRequestHttpException 异常 因为$id 参数收到数字值 ['123']实际不是字符串.

有关Controller的生命周期及任何那边未有涉及的,能够去官方网址看详细的阐述。

模型

讲完了入口的Controller,以后我们的话说MVC中最最最最关键的多少模型层,这一层负担数据的重组管理,包蕴职业逻辑调控,从数据库拿出多少,打包数据,缓存操作,再次回到给Controller等一多重操作,可谓是大家一般业务逻辑专门的学问中每一天津高校部分时日都在撸的代码了。

模型可因此持续 yiibaseModel 或它的子类定义,基类yiibaseModel接济广大实用的特色:

Model 类也是越来越多高级模型如Active Record 活动记录的基类,不得不说,对于数据库操作不在行的相恋的人能够品味一下Active Record,Yii的那几个特点令你操作数据库像操作对象同样简单。

概念属性,说白了也正是概念model里面包车型地铁变量。

namespace appmodels;

use yiibaseModel;

class ContactForm extends Model
{
    public $name;
    public $email;
    public $subject;
    public $body;
}

事先做过java,eclipse自动生成get,set方法,感到相当低价,这边,一般情形下无需生成get,set方法,除非您的数据库操作是经过Active Record实行的,你才供给去掩饰魔术点子如__get()__set()使属性像平日对象属性被访谈。

对于model里面属性的访问,那要谢谢yiibaseModel帮衬 ArrayAccess 数组访谈 和 ArrayIterator 数组迭代器。能够使用如下二种方法对品质举行拜见,是public属性哟。

$model = new appmodelsContactForm;

// "name" 是ContactForm模型的属性
$model->name = 'example';
echo $model->name;

$model = new appmodelsContactForm;

// 像访问数组单元项一样访问属性
$model['name'] = 'example';
echo $model['name'];

// 迭代器遍历模型
foreach ($model as $name => $value) {
    echo "$name: $valuen";
}

脾性标签,一般接纳在输入错误的唤起处,属性标签是视图一部分,不过在模型中阐明标签平常十分便于,并可行程十一分简短可采用代码。大家那边不做索求,一般在后台应用中比较少提到。感兴趣的相恋的人能够去官方文当详查。

质量的规范很首要,常规的操作是不允许八个model之间交互调用各自的习性的,如非须要,一般model中相比正规的个性放到全局变量中去决定,后台应用中,可必要model操作的数目均是根源客户的,大家要求做的更加多的是对顾客输入的支配。你或许在平日的办事中对这个客商输入的主宰直接就动用了,枫爷在那边给我们一个非常的小的小心,千万不可能那样干,有几步还是内需做的,为了安全性。其一,xss攻击的幸免;其二,顾客输入的注解。

xss的攻击,Yii提供了对应的法子应对,假使这几个参数不对数据库实行操作,一般景色下不需求验证,假若急需对数据库举办求证,供给实行xss验证,具体的实例代码百度时而,一大堆,这里就不做讲明啦。

对于客商输入的证实,最佳的做法是在Controller里面前遭遇客户的行事展费用配,也正是重写behaviors那一个点子,然后对每种action举办认证。

'validation' => [
                'class' => 'extcontrollerbehaviorValidation',
                'verifyPath' => 'appmodulesapimodulesv1modelsvalidation\',
                'indexName' => 'body',
                'enabled' => true
],

骨子里,是不是须求登陆验证,是还是不是要求缓存都足以在behaviors里面举办布置。

那般区分开来不但能够幸免在model里面写过多校验代码,也得以使您的model层特别清晰简洁。

其实这些理应是在Controller那边说的,既然那边境海关周密据校验,就一笔带过啦~具体的如何操作,我们会在底下一节【过滤器】中详解。

对此数据的获得,数据库照旧缓存,大家在接下去的章节中持续上课,那边就不细究了,进入下一个环节,View。

对此Model,也就这么多,别的的和写一般的function一样,写作业逻辑就足以啦,须要稳重的都说了哈~未来有补充在评论栏。

视图

后端接口的使用中,这么些模块非常少被选拔到,假使我们对那么些模块感兴趣,能够去官方网址详查,小编那边的艺术很简短暴力,直接return给客商数据就可以。

不要忘了,前端须要什么样的数码格式,我们那边供给在结尾return的时候encode一下哈。最常用的实在json格式啦。

public function formatJson($data = [])
    {
        Yii::$app->response->format = yiiwebResponse::FORMAT_JSON;
        return $data;
    }

模块

您或者未有在Yii2.0的源代码中找到关于模块的代码,那是因为Yii最大的优势是支付后台系统,并未想过需求把业务逻辑切割的那么细,大家在平凡开销后台接口的时候,会有相当多独立的系统,比方说顾客模块,订单模块,支付模块等等等等。这模块的优势就显得出来了,每一个系统三个模块,明明白白。

怎么着创设模块呢?上边来一步步的搞通晓。

模块是独立的软件单元,由模型, 视图, 调节器和别的协理组件组成,是还是不是以为正是个小型的MVC模型,没有错,各种模块都是三个单独的单元。

行使模块必得在行使大旨中布局它,终端客户能够访谈在接纳中央中已设置的模块的调整器。

一般来讲例子显示贰个模型的目录结构:

app/
    Module.php                   模块类文件
    controllers/                 包含控制器类文件
        DefaultController.php    default 控制器类文件
    models/                      包含模型类文件
    views/                       包含控制器视图文件和布局文件

Module.php是基础模块类,承接yiibaseModule的模块类,该类文件向来放在模块的yiibaseModule::basePath【模块对应的主目录】下。必得能被活动加载。

在行使中央中安顿模块,如下示例

$config = [
    'id' => 'app.name',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'language' => 'zh-CN',
    'components' => [
       ...
    ],
    'params' => $params,
    'modules' => [
        'user' => [
            'class' => 'appmodulesuserUser',
        ],
        'goods' => [
            'class' => 'appmodulesgoodsGoods',
        ],
        'store' => [
            'class' => 'appmodulesstoreStore',
        ],
        'supply' => [
            'class' => 'appmodulessupplySupply',
        ],
        'order' => [
            'class' => 'appmodulesorderOrder',
        ],
        'stock' => [
            'class' => 'appmodulesstockStock',
        ],
        'pay' => [
            'class' => 'appmodulespayPay',
        ],
        'message' => [
            'class' => 'appmodulesmessageMessage',
        ],
    ],
    'aliases' => $aliases,
    'defaultRoute' => 'admin'
];

主导使用中安顿的模块就对准刚刚创立的模块基础类。

各类模块能够有谈得来单独的安排文件,将模块中必要使用的一块儿的参数放到那几个布局文件中,并在模块基础类中加多进去。

上边即是本人的用户模块的目录和代码

图片 9

<?php
namespace appmodulesgoods;

use Yii;

class Goods extends yiibaseModule
{
    public $controllerNamespace = 'appmodulesgoodscontrollers';

    public function init()
    {
        parent::init();

        Yii::configure($this, require(__DIR__ . '/config.php'));
    }
}

拜会路由

和拜望应用的调整器类似,路由也用在模块中央调控制器的寻址, 模块中调控器的路由必得以模块ID最早,接下去为调控器ID和操作ID。 比方,假定应用使用二个名字为 forum 模块,路由forum/post/index 代表模块中 post 调整器的 index 操作, 假若路由只包蕴模块ID,默认为 default 的yiibaseModule::defaultRoute 属性来调节接纳哪个调控器/操作, 约等于说路由 forum 恐怕意味着 forum 模块的 default 控制器。

貌似访问模块的措施如下:

// 获取ID为 "forum" 的模块
$module = Yii::$app->getModule('forum');

// 获取处理当前请求控制器所属的模块
$module = Yii::$app->controller->module;

模块在大型项目中一般使用,那个项目标特色可分组,每种组富含部分强相关的风味, 每特性子组能够做成三个模块由特定的开垦人士和开拓组来支付和保障。

在特色组上,使用模块也是采用代码的好措施,一些常用特性,如客商管理,商量管理,能够付出成模块, 那样在相关项目中国和北美洲常轻易被录用。无耻的抄袭了官方网址文书档案的特等实行,其实个人感到官方网址文书档案的特级时间是最给力的内容,其余故事情节都太刚强了^_^

过滤器

在模块那一节,我们关系三个校验的神器,behavior,过滤器是Controller动作实施此前或之后推行的靶子,所以本身说应该投身Controller一节去讲,但是在model层数据处理中关系了,就在那边一笔代了下,现在来详细的说说这几个呢。

过滤器可含蓄 预过滤(过滤逻辑在动作之前) 或 后过滤(过滤逻辑在动作之后),也可同有的时候间包涵两个。

笔者们地点仅是聊到了过滤器的三性子能,validation,这也是自己自定义的三天性质,用于校验客商输入的准确。

全部的官方网址对behaviors的概念如下:

public function behaviors()
{
    return [
        [
            'class' => 'yiifiltersHttpCache',
            'only' => ['index', 'view'],
            'lastModified' => function ($action, $params) {
                $q = new yiidbQuery();
                return $q->from('user')->max('updated_at');
            },
        ],
    ];
}

调控器类的过滤器默许使用到此类的兼具action,你能够在only参数中钦赐应用到哪多少个action。也能够配置yiibaseActionFilter::except属性使一些动作不进行过滤器。

一般情况下,我们应用预过滤,非常少会被用到后过滤,他们有甚分化吧。

预过滤

  • 按顺序实践应用中央中behaviors()列出的过滤器。
  • 按顺序实施模块中behaviors()列出的过滤器。
  • 按顺序实行调控器中behaviors()列出的过滤器。
  • 一经任性过滤器终止动作实践,前边的过滤器(蕴含预过滤和后过滤)不再进行。
  • 得逞通过预过滤后进行动作。

后过滤

  • 倒序实行调节器中behaviors()列出的过滤器。
  • 倒序推行模块中behaviors()列出的过滤器。
  • 倒序实践应用核心中behaviors()列出的过滤器。

成立过滤器,承袭 yiibaseActionFilter 类并覆盖 yiibaseActionFilter::beforeAction() 和/或 yiibaseActionFilter::afterAction() 方法来创设动作的过滤器,前面八个在动作推行此前实行,前者在动作施行之后实践。

下边是自个儿在类型中央银行使的集体验证器。

<?php
namespace extcontrollerbehavior;

use Yii;
use yiibaseActionFilter;
use yiibaseException;

class Validation extends ActionFilter
{
    public $enabled = true; //默认打开验证

    public $verifyPath = null;//验证目录,必填项.命名空间格式填写

    public $whiteParams = null; //过滤之后的参数,供控制器使用

    public $indexName = '';

    public function beforeAction($action)
    {
        if (!$this->enabled) {
            return true;
        }

        return $this->_check($action);
    }

    protected function _check($action)
    {
        if (empty($this->verifyPath)) {
            throw new Exception('验证目录不存在!');
        }

        //目前只支持两级
        $groups = explode('/', $this->owner->id);
        if (is_array($groups) && count($groups) >= 2) {
            $fileName = ucfirst($groups[0]).ucfirst($groups[1]);
        } else {
            $fileName = ucfirst($this->owner->id);
        }
        unset($groups);
        $className = $this->verifyPath . $fileName;

        if (!class_exists($className)) {
            return true;
        }

        $actionId = $action->id;

        $v = new $className($this->owner->getParam($this->indexName) ?: []);

        if (!method_exists($v, $actionId)) {
            return true;
        }

        $v->{$actionId}();
        if (!$v->validate(null, false)) {
            $errorList = [];
            $errors = $v->getErrors();

            foreach ($errors as $field => $error) {
                $errorList[] = implode(' ', $error);
            }

            Yii::$app->getResponse()->data = $this->owner->getBehavior('format')->afterAction($action, $this->owner->sendError(implode(' & ', $errorList), 400));
            return false;
        }
        $this->whiteParams = $v->getAttributes();
        return true;
    }
}

在Controller中的behaviors中增添一条validation就能够对一些action进行验证啦。

'validation' => [
                'class' => 'extcontrollerbehaviorValidation',
                'verifyPath' => 'appmodulesgoodscontrollervalidation\',
                'indexName' => 'body',
                'enabled' => true
            ],

verifyPath便是被认证的条条框框路线。如若是表达参数,就对Controller下的上上下下action实行验证咯。

再来看下是何等编写这个个准则的。创造对应modules的validation。

<?php
namespace appmodulesgoodscontrollersvalidation;

use appmodulesapimodelsbaseBaseValidation;

class SupplyGoods extends BaseValidation
{

    public function detail()
    {
        $this->defineAttributes('goodsId');
        $this->addRule('goodsId', 'number')->addRule('goodsId', 'required');
    }

    public function add()
    {
        $this->defineAttributes('goodsTitle,goodsPrice,minNum,catId,childCatId,showImages,detailImages,goodsAttr');
        $this->addRule('goodsTitle', 'trim')->addRule('goodsTitle', 'required');

        $this->addRule('goodsPrice', 'required');

        $this->addRule('catId', 'number')->addRule('catId', 'required')
            ->addRule('childCatId', 'number')->addRule('childCatId', 'required');


        if (!is_array($this->showImages) || count($this->showImages) == 0) {
            $this->addError('showImages', '商品展示图片必传!');
        }

        if (!is_array($this->detailImages) || count($this->detailImages) == 0) {
            $this->addError('detailImages', '图文详情必传!');
        }

        if (empty($this->goodsAttr['color'])
            || empty($this->goodsAttr['style_id'])
            || empty($this->goodsAttr['size_ids'])
        ) {
            $this->addError('goodsAttr', '请设置库存');
        }
    }

    public function update()
    {
        $this->defineAttributes('goodsId,goodsTitle,goodsPrice,minNum,catId,childCatId,showImages,detailImages,goodsAttr');
        $this->addRule('goodsTitle', 'trim')->addRule('goodsTitle', 'required');

        $this->addRule('goodsPrice', 'required');

        $this->addRule('catId', 'number')->addRule('catId', 'required')
            ->addRule('childCatId', 'number')->addRule('childCatId', 'required')
            ->addRule('goodsId','number')->addRule('goodsId','required');


        if (!is_array($this->showImages) || count($this->showImages) == 0) {
            $this->addError('showImages', '商品展示图片必传!');
        }

        if (!is_array($this->detailImages) || count($this->detailImages) == 0) {
            $this->addError('detailImages', '图文详情必传!');
        }

        if (empty($this->goodsAttr['color'])
            || empty($this->goodsAttr['style_id'])
            || empty($this->goodsAttr['size_ids'])
        ) {
            $this->addError('goodsAttr', '图片属性必传!');
        }
    }

    public function edit()
    {
        $this->defineAttributes('goodsId');
        $this->addRule('goodsId', 'number')->addRule('goodsId', 'required');
    }

    public function lists()
    {

    }

    public function delete()
    {
        $this->defineAttributes('goodsId');
        $this->addRule('goodsId', 'number')->addRule('goodsId', 'required');
    }

    public function category()
    {
        $this->defineAttributes('childCatId');
        $this->addRule('childCatId', 'number')->addRule('childCatId', 'required');
    }

}

BaseValidation是自己写的贰个基类,对一些全局要求评释的习性举行表明,传承DynamicModel。

验证类的名号SupplyGoods是基于路线来的,作者的GoodsController在controllers里面包车型客车supply目录下,所以命名成SupplyGoods。

addRule此前必供给定义attributes

$this->defineAttributes('childCatId');
$this->addRule('childCatId', 'number')->addRule('childCatId', 'required');

各种function的称号对应action前边的操作ID。

那是自家要好定义的一个过滤器,其实,Yii提供了一组常用过滤器,在yiifilters命名空间下,有个别如故很科学的,大家感兴趣的话可以去官互连网看见。

从那之后,这一章基础框架部分就整个给咱们说完了,累死小编了,撸博客不易呀,且行且保养,但是自个儿的Yii体系除了这一章以外,还将会给大家带来别的的几章,大家连连关怀,有吗难点在评论区提议来,笔者会在第一时间给大伙解答哈O(∩_∩)O

本文由星彩网app下载发布于计算机编程,转载请注明出处:从路由到调控器,从布局文件的角度去掌握Yii2

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。