Yii 学习笔记

本文详细探讨了Yii框架的请求处理逻辑、关键知识点,包括属性、事件、行为、MVC模式等。强调了从模型开始构建代码的重要性,以及Yii中的组件、配置、别名、类自动加载和依赖注入等高级特性。还提到了过滤器、资源管理和错误处理策略,为开发者提供了深入理解Yii的全面指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于写代码的顺序

在学习使用表单的章节中,作者先写Model的代码,然后写controller的代码,最后写View的代码。这不是一个偶然,在使用thinkPHP框架写代码的时候,也同样遇到过类似的问题,开始写代码的时候不知道从那里入手比较顺。实际上,如果模型没有定义好,证明整个业务逻辑没有理清,没有理清业务当然就构建不出模型来,所以教程里面的顺序安排也给了自己指导意见,将来的代码逻辑里面应该从模型开始,快速搭建代码框架,跑通业务流程,然后细化细节。

Yii框架处请求的逻辑

这里写图片描述

小知识点

1、yii\base\Model 被用于普通模型类的父类并与数据表无关。yii\db\ActiveRecord 通常是普通模型类的父类但与数据表有关联

2、表达式 Yii::$app 代表应用实例,它是一个全局可访问的单例。同时它也是一个服务定位器,能提供 request,response,db 等等特定功能的组件。

3、当一个操作中调用了 yii\web\Controller::render() 方法时,它将会按 views/控制器 ID/视图名.php 路径加载 PHP 文件。主要的两个目录是:controllers和views,对应关系是一个controller对应views的一个目录,对应规则是”控制器 ID“。
Yii中处理控制器ID和操作 ID是一样的规则, 总是被以小写处理,如果一个ID 由多个单词组成,单词之间将由连字符连接(如 create-comment)。ID 映射为控制器名或者方法名时移除了连字符,将每个单词首字母大写,并加上 action 前缀。 例子:操作 ID create-comment 相当于方法名 actionCreateComment。

关键知识点

  • 属性(Property)
    个人偏向于把“属性”直接等同于面对相对编程的“成员变量”,yii里把面向对象的成员变量以术语Property来表示。
    PHP是弱类型语言,可以随时给对象新增成员变量,Yii里通过客户化的__set()和__get()限制了这个能力(yii\base\Object),从而确保了成员变量的安全性、封装性。严格来处理应该尽量不写public的成员变量,都写private,且都要使用get和set方法来获取私有变量的,可是PHP的魔术方法__set()和__get()又可以让我们具有向访问公有成员变量一样访问私有成员变量。因此总括起来,我个人理解,yii里属性的概念就是成员变量,并没有差异。
    当然,安全性和封装性所带来的好处还是很多的。 一般而言,成员变量对外不可见是比较好的编程习惯。特别是突然某一天业务需求变更某个成员变量展示的长度、或者格式、或者其他客户化变更的时候,这个编程习惯会带来很畅快的体验。

  • yii\base\Object / yii\base\Component
    Yii里面提供了Object和Component两个顶层基类,Component由于增加了event和behavior这两个特性, 在方便开发的同时,也牺牲了一定的效率。 如果开发中不需要使用event和behavior这两个特性,比如表示一些数据的类。 那么,可以不从Component继承,而从Object继承。

  • 事件(Event)yii\base\Event
    事件既是代码解耦的一种方式,也是设计业务流程的一种模式。
    如果没有事件这个功能,类似功能怎么做?
    如果没有事件的处理机制,每次遇到某个特定场景或者特定值的时候,就需要执行某段固定的代码,这段代码如果只被一个地方使用,那没有事件机制也没什么不妥,如果这个代码被很多地方使用,就需要把代码抽取出来成为独立的函数,方便被多个地方调用。如果只调用这个函数自己就也还好,如果调用多个函数,就得写多行调用代码,行数足够多之后很自然就会想办法把函数都封装都一个统一的函数里面进行管理。这样的代码逻辑再往上抽象和优化组织就会成为事件这种机制。
    适合使用事件的场景,做一件事触发接下来好多个处理步骤的场景。而组件提供的事件处理程序其实仅仅是同步的,不是异步的,就是handler一定要即时返回处理结果。
    事件的绑定可以在运行时以代码的形式进行绑定,也可以在配置中进行绑定,这个配置生效的过程其实也是在运行时的。

  • 行为(Behavior)yii\base\Behavior
    使用行为(behavior)可以在不修改现有类的情况下,对类的功能进行扩充。
    关于属性的注入是通过set和get函数实现的,而函数的注入是通过__call()函数实现的。
    要理解行为与继承和特性(Traits) 的区别。行为更多是在给原有类定义添加功能的时候使用的,而这些要被添加的功能又要被其他类进行共享,如果没有其他类进行共享,就没有必要做这样的事情。另外,这些功能还跟原类没有明显的继承关系。而Yii中的行为更多是为了扩展事件的处理能力而设计的,并不仅仅是为了增加类的特性。

  • MVC模式
    Model是指数据模型,是对客观事物的抽象。
    View是指视图,也就是呈现给用户的一个界面,是model的具体表现形式,也是收集用户输入的地方。
    Contorller指的是控制器,主要负责与model和view打交道。

    web网站的开发工作很大部分是集中在model层,model层的代码量会非常多,必然的选择就是对model进行分层、分模块,在Yii框架的gii工具的帮助下,其实针对model会产生三个类:model、modelQuery、modelSearch , 我个人的理解就是,model基本是跟数据库表一一对应的(但是也不排出有扩展),query是写业务逻辑的地方,search是编写查询条件的类,针对不同业务逻辑需要不同的查询逻辑。

  • 依赖注入
    使用第三方资源时,都需要优先考虑依赖注入的设计模式,因为基本上是会出现多种类型资源供选择的情况。譬如:发送邮件、短信;拨打电话;支付;连接数据库等等。在代码逻辑过程中,需要使用很多第三方资源的话,就可以考虑依赖注入的设计思路。
    1、首先要考虑 依赖倒置原则(Dependence Inversion Principle, DIP),上层定义接口,下层实现接口,其实下层更多的是针对第三方资源提供的操作函数进行二次封装,以便对本系统提供公共操作的入口,这样每追加资源的时候就会有很熟悉的代码流程。这是基本原则,是实现依赖注入的设计模式的基础。

2、依赖倒置是一种编程思想,在这种思想的指导下,新加资源只需要编写一个对应的接口类即可。但是实例化接口类的代码还是得写,这样也会改动原来的代码,这个改动不管多少,都会多多少少引入BUG。IoC,控制反转(Inversion of Control, IoC),核心思想是将类(上层)所依赖的单元(下层)的实例化过程交由第三方来实现。这个具有实例化对象能力的第三方有点像工厂方法,但是不能说是工厂方法,工厂方法更多是用于创建同类资源,而这个第三方是要用于创建所有对象的,是一个更高层的抽象,在Yii框架中这个第三方叫做”控制反转容器“,提供了动态地创建、注入依赖单元,映射依赖关系等功能。

Controller的重点内容

1、每个控制器都有一个由 yii\base\Controller::defaultAction 属性指定的默认操作。默认是index。
2、controller里面有内联操作 和 独立操作 的概念,但是在项目里,更好的做法是通过继承来共享操作。

Model的重点内容

1、model存储数据的时候是没有过滤特殊标签的,展示数据的时候要处理好跨域攻击的隐患。
2、控制场景的使用个数,通过继承的方式独立各个场景比用scenarios好。
3、块赋值只处理安全属性,非安全属性需要手工处理。

View的重点内容

1、 将预定义变量列到视图文件头部注释处,这样可被IDE编辑器识别。
2、当创建生成HTML页面的视图时,在显示之前将用户输入数据进行转码和过滤非常重要。纯文本可调用 yii\helpers\Html::encode() 进行转码,HTML内容可调用 yii\helpers\HtmlPurifier()
3、存储渲染后的页面到数据库或者静态页面可以用:
echo \Yii::app>view>renderFile(@app/views/site/license.php);4yii\base\Viewyii\base\View::params5this 和 contentyii\base\Viewyii\base\Controller::render()6访this 和 $content,前者对应和普通视图类似的yii\base\View 视图组件 后者包含调用yii\base\Controller::render()方法渲染内容视图的结果。

Modules

关于modules,个人觉得有可能的话尽量避免使用。因为既然考虑到Modules了,为啥不考虑分独立系统呢?分独立系统会让整个项目更简洁,更独立。也降低开发人员破坏代码的风险。
不过,如果是采用过度方案就可以考虑下使用。就是在独立子系统之前使用modules做代码隔离,方便将来独立成子系统,不过有时候这是一个谎言,隔离之后还有没有动力独立成子系统,是一个比较有意思的问题。

Filters(非常重要)

过滤器是 控制器 动作 执行之前或之后执行的对象,记住是控制器执行前或后。 例如访问控制过滤器可在动作执行之前来控制特殊终端用户是否有权限执行动作, 内容压缩过滤器可在动作执行之后发给终端用户之前压缩响应内容。
过滤器本质上是一类特殊的 行为,所以使用过滤器和 使用 行为一样。
核心过滤器:
- yii\filters\AccessControl:决定允许还是拒绝请求动作的执行, 如果没有规则符合,访问就会被拒绝。
- 认证方法过滤器:通常在实现RESTful API中使用。
- yii\filters\ContentNegotiator:ContentNegotiator支持响应内容格式处理和语言处理。 通过检查 GET 参数和 Accept HTTP头部来决定响应内容格式和语言。
- yii\filters\HttpCache:HttpCache利用Last-Modified 和 Etag HTTP头实现客户端缓存。
- yii\filters\PageCache:PageCache实现服务器端整个页面的缓存。
- yii\filters\RateLimiter:RateLimiter 根据 漏桶算法 来实现速率限制。
- yii\filters\VerbFilter:VerbFilter检查请求动作的HTTP请求方式是否允许执行, 如果不允许,会抛出HTTP 405异常。
- yii\filters\Cors:跨域资源共享 CORS 机制允许资源可以通过其他域名访问获取。

widget

小部件是Yii框架中一套管理前端组件的方案,是一套复用前端代码的好方法。只可惜在多数项目里面都没有被很好地使用,如果我来做开发规范的话,我觉得我会把这种程度的复用使用到极致的。
- yii\jui\DatePicker:日期选择器小部件
- yii\widgets\ActiveForm:
- yii\widgets\Menu:
- yii\widgets\LinkPager:
小部件设计时应是独立的,也就是说使用一个小部件时候, 可以直接丢弃它而不需要额外的处理。 但是当小部件需要外部资源如CSS, JavaScript, 图片等会比较棘手, 幸运的时候Yii提供 资源包 来解决这个问题。

Assets前端资源

当在视图中注册一个资源包, 在渲染Web页面时会包含包中的CSS和JavaScript文件。
定义资源包:资源包指定为继承yii\web\AssetBundle的PHP类。
Cache Busting:通过参数来让浏览器刷新缓存文件。
合并和压缩资源:一个Web页面可以包含很多CSS 和/或 JavaScript 文件,为减少HTTP 请求和这些下载文件的大小, 通常的方式是在页面中合并并压缩多个CSS/JavaScript 文件为一个或很少的几个文件, 并使用压缩后的文件而不是原始文件。

如果后台工作人足够或者前端工作人员有能力,都可以考虑使用yii来做资源管理,看起来功能还是很全很强大的,但是对前端开发有一定的要求。

扩展(Extensions)

快速获取SDK或者自己开发SDK。
有些优秀的扩展可以直接使用,阅读过其中一两个的源码之后,熟悉扩展的开发规范和方法之后,遇到一些需求可以先搜搜是否有好用的扩展直接使用。在packlist里面搜。

路由

当入口脚本在调用 yii\web\Application::run() 方法时,它进行的第一个操作就是解析输入的请求,然后实例化对应的控制器操作处理这个请求。 该过程就被称为引导路由(routing)。
普通的格式优化
Rest支持
创建URL
URL后缀

错误处理

  • 使用错误处理器:yii\web\ErrorHandler 注册成一个名称为errorHandler应用组件即可完成全局的错误处理机制。
  • 使用错误操作 :yii\web\ErrorHandler::errorAction 属性错误路由到一个操作, 上述配置表示不用显示函数调用栈信息的错误会通过执行site/error操作来显示。
  • 自定义错误格式 :在做API接口的时候就比较有用了。

日志

  • Yii::trace():记录一条消息去跟踪一段代码是怎样运行的。这主要在开发的时候使用。
  • Yii::info():记录一条消息来传达一些有用的信息。
  • Yii::warning():记录一个警告消息用来指示一些已经发生的意外。
  • Yii::error():记录一个致命的错误,这个错误应该尽快被检查。

  • 日志目标:
    一个日志目标是一个 yii\log\Target 类或者它的子类的实例。 它将通过他们的严重层级和类别来过滤日志消息,然后将它们导出到一些媒介中。

  • 性能分析:
    性能分析是一个特殊的消息记录类型,它通常用在测量某段代码块的时间, 并且找出性能瓶颈是什么。

组件(Component)

Yii的组件是 yii\base\Component 类或其子类的实例,主要提供了三项功能:
- 属性(Property):要注意于类成员变量做区分。
- 事件(Event):事件可以将自定义代码“注入”到现有代码中的特定执行点。这种机制可以很好得控制代码粒度,提高代码的复用能力。
- 行为(Behavior):可以无须改变类继承关系即可增强一个已有的yii\base\Component 类功能。更多的情况下是结合事件来组织代码。

配置

在 Yii 中,创建新对象和初始化已存在对象时广泛使用配置。配置通常包含被创建对象的类名和一组将要赋值给对象属性的初始值。还可能包含一组将被附加到对象事件上的句柄。和一组将被附加到对象上的行为。
Yii::createObject() 方法接受一个配置数组并根据数组中指定的类名创建对象。对象实例化后,剩余的参数被用来初始化对象的属性,事件处理和行为。

别名(Aliases)

通过 Yii::setAlias() 定义的别名称为根别名,而用他们衍生出去的别名成为衍生别名。

类自动加载(Autoloading)

要使用 Yii 的类自动加载器,你需要在创建和命名类的时候遵循两个简单的规则:
- 每个类都必须置于命名空间之下 (比如 foo\bar\MyClass)。
- 每个类都必须保存为单独文件,且其完整路径能用以下算法取得:

// $className 是一个开头包含反斜杠的完整类名
$classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');

Yii 类自动加载器支持类映射表功能,该功能会建立一个从类的名字到类文件路径的映射。优先级更高。

服务定位器

服务定位器是一个了解如何提供各种应用所需的服务(或组件)的对象。 在服务定位器中,每个组件都只有一个单独的实例,并通过ID 唯一地标识。 用这个 ID 就能从服务定位器中得到这个组件。
最常用的服务定位器是application(应用)对象,可以通过 \Yii::$app 访问。

依赖注入容器

Yii 通过 yii\di\Container 类提供 DI 容器特性。它支持如下几种类型的依赖注入:
- 构造方法注入;
- Setter 和属性注入;
- PHP 回调注入.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值