属性:

public function __get($name)              // 这里$name是属性名
{
$getter = 'get' . $name; // getter函数的函数名
if (method_exists($this, $getter)) {
return $this->$getter(); // 调用了getter函数
} elseif (method_exists($this, 'set' . $name)) {
throw new InvalidCallException('Getting write-only property: '
. get_class($this) . '::' . $name);
} else {
throw new UnknownPropertyException('Getting unknown property: '
. get_class($this) . '::' . $name);
}
} // $name是属性名,$value是拟写入的属性值
public function __set($name, $value)
{
$setter = 'set' . $name; // setter函数的函数名
if (method_exists($this, $setter)) {
$this->$setter($value); // 调用setter函数
} elseif (method_exists($this, 'get' . $name)) {
throw new InvalidCallException('Setting read-only property: ' .
get_class($this) . '::' . $name);
} else {
throw new UnknownPropertyException('Setting unknown property: '
. get_class($this) . '::' . $name);
}
}

someObject->foo实际是调用someObject->getFoo()

someObject->foo = $some_value 实际是 someObject->setFoo($some_value)

如下的Post类,实现了可读可写的属性title:

class Post extends yii\base\Object    // 第一步:继承自 yii\base\Object
{
private $_title; // 第二步:声明一个私有成员变量 public function getTitle() // 第三步:提供getter和setter
{
return $this->_title;
} public function setTitle($value)
{
$this->_title = trim($value);
}
}

这样好处多多

Component继承于yii\base\object, 具有以下三个重要特征

  属性

  事件

  行为

事件:

yii\base\Component::on() 就是用来绑定的

$person = new Person;

// 使用PHP全局函数作为handler来进行绑定
$person->on(Person::EVENT_GREET, 'person_say_hello'); // 使用对象$obj的成员函数say_hello来进行绑定
$person->on(Person::EVENT_GREET, [$obj, 'say_hello']); // 使用类Greet的静态成员函数say_hello进行绑定
$person->on(Person::EVENT_GREET, ['app\helper\Greet', 'say_hello']); // 使用匿名函数
$person->on(Person::EVENT_GREET, function ($event) {
echo 'Hello';
});

行为:

行为是把一个类绑定到另一个类, 让第二个类有第一个类的属性和方法. 即:不改变现有类的情况下, 对类的功能进行扩充

使用行为的大致流程

  • 从 yii\base\Component 派生自己的类,以便使用行为;
  • 从 yii\base\Behavior 派生自己的行为类,里面定义行为涉及到的属性、方法;
  • 将Component和Behavior绑定起来;
  • 像使用Component自身的属性和方法一样,尽情使用行为中定义的属性和方法。

YII模式

MVC模式

Model主要是数据, 业务逻辑, 业务规则. 这部分应该比较稳定, 产品成型后不经常改变.

   包括数据, 行为, 方法.

   提供有结构的数据, 原始的数据, 如数组, 队列.

   要和Controller区分开, 好的设计是胖Model, 瘦Controller. Controller只是协调Model和View, 业务相关的放在Model里

View是展示页面, 主要是HTML部分代码, 简单的循环输出, 不会直接调用Model数据.

Controller是负责Model和View之间的桥梁, 负责决定使用哪些Model, 对应哪些View.

   处理用户的请求, 只限于处理用户的请求, 不应该对数据有任何操作和预处理, 这些工作应由Model完成.

    调用Model的读方法, 获取数据, 直接传递给视图, 供显示. 涉及到多个Model时, 有关的逻辑应交给Model来完成.

   调用Model类方法, 进行写操作.

   调用视图渲染函数, 形成对用户Request的Response.

依赖注入

在Web应用中,很常见的是使用各种第三方Web Service实现特定的功能,比如发送邮件、推送微博等。 假设要实现当访客在博客上发表评论后,向博文的作者发送Email的功能,通常代码会是这样:

// 为邮件服务定义抽象层
interface EmailSenderInterface
{
public function send(...);
} // 定义Gmail邮件服务
class GmailSender implements EmailSenderInterface
{
... // 实现发送邮件的类方法
public function send(...)
{
...
}
} // 定义评论类
class Comment extend yii\db\ActiveRecord
{
// 用于引用发送邮件的库
private $_eMailSender; // 初始化时,实例化 $_eMailSender
public function init()
{
...
// 这里假设使用Gmail的邮件服务
$this->_eMailSender = GmailSender::getInstance();
...
} // 当有新的评价,即 save() 方法被调用之后中,会触发以下方法
public function afterInsert()
{
...
//
$this->_eMailSender->send(...);
...
}
}

构造函数注入

构造函数注入通过构造函数的形参,为类内部的抽象单元提供实例化。 具体的构造函数调用代码,由外部代码决定。具体例子如下:

// 这是构造函数注入的例子
class Comment extend yii\db\ActiveRecord
{
// 用于引用发送邮件的库
private $_eMailSender; // 构造函数注入
public function __construct($emailSender)
{
...
$this->_eMailSender = $emailSender;
...
} // 当有新的评价,即 save() 方法被调用之后中,会触发以下方法
public function afterInsert()
{
...
//
$this->_eMailSender->send(...);
...
}
} // 实例化两种不同的邮件服务,当然,他们都实现了EmailSenderInterface
sender1 = new GmailSender();
sender2 = new MyEmailSender(); // 用构造函数将GmailSender注入
$comment1 = new Comment(sender1);
// 使用Gmail发送邮件
$comment1.save(); // 用构造函数将MyEmailSender注入
$comment2 = new Comment(sender2);
// 使用MyEmailSender发送邮件
$comment2.save();

属性注入

与构造函数注入类似,属性注入通过setter或public成员变量,将所依赖的单元注入到类内部。 具体的属性写入,由外部代码决定。具体例子如下:

// 这是属性注入的例子
class Comment extend yii\db\ActiveRecord
{
// 用于引用发送邮件的库
private $_eMailSender; // 定义了一个 setter()
public function setEmailSender($value)
{
$this->_eMailSender = $value;
} // 当有新的评价,即 save() 方法被调用之后中,会触发以下方法
public function afterInsert()
{
...
//
$this->_eMailSender->send(...);
...
}
} // 实例化两种不同的邮件服务,当然,他们都实现了EmailSenderInterface
sender1 = new GmailSender();
sender2 = new MyEmailSender(); $comment1 = new Comment;
// 使用属性注入
$comment1->eMailSender = sender1;
// 使用Gmail发送邮件
$comment1.save(); $comment2 = new Comment;
// 使用属性注入
$comment2->eMailSender = sender2;
// 使用MyEmailSender发送邮件
$comment2.save();

参考自http://www.digpage.com/index.html, 如需学习YII2, 请转自前面链接, <深入理解Yii2.0>, 来获取更多内容.

yii2 学习中的更多相关文章

  1. YII2学习第一天

    YII2学习第一天,之前稍微看了看TP,感觉和自己的理念不是很符合,然后转学YII2了. 使用的文档是https://github.com/yiisoft/yii2/tree/master/docs/ ...

  2. 记录Python学习中的几个小问题

    记录Python学习中的几个小问题,和C#\JAVA的习惯都不太一样. 1.Django模板中比较两个值是否相等 错误的做法 <option value="{{group.id}}&q ...

  3. 深度学习中的Data Augmentation方法(转)基于keras

    在深度学习中,当数据量不够大时候,常常采用下面4中方法: 1. 人工增加训练集的大小. 通过平移, 翻转, 加噪声等方法从已有数据中创造出一批"新"的数据.也就是Data Augm ...

  4. Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)

    Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...

  5. Java 需要记得、了解的关键词 (Java 学习中的小记录)

    Java 需要记得.了解的关键词 (Java 学习中的小记录)     作者:王可利(Star·星星) 总结:本次随笔,仅且拿来平时翻阅记忆用

  6. Java学习中,常用的命令管理(Java 学习中的小记录)

    Java学习中,常用的命令管理      作者:王可利(Star·星星) 一.Window中常见的dos命令 在哪里操作dos命令: Win7 ---> 开始  ---->所有程序---& ...

  7. Java基础学习中一些词语和语句的使用

    在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...

  8. 有关JAVA基础学习中的集合讨论

        很高兴能在这里认识大家,我也是刚刚接触后端开发的学习者,相信很多朋友在学习中都会遇到很多头疼的问题,希望我们都能够把问题分享出来,把自己的学习思路整理出来,我们一起探讨一起成长.    今天我 ...

  9. ubuntu下30天自制操作系统还在继续学习中

    操作系统还在学习中,进度不是非常确定,近期学习到了第13天的中部,由于把ucgui移植上去花了一点时间. 同一时候为了方便代码的兴许管理和分享,也为了学习github的代码管理使用思想, 所以建立了一 ...

随机推荐

  1. js读取json数据(php传值给js)

    <?php $array =array('fds','fdsa','fdsafasd');  // json_encode($array); ?> <html> <hea ...

  2. trade 主要前端组件

    jQuery Custombox http://www.jqueryfuns.com/resource/view/27

  3. C#中窗体的互相访问

    1.在父窗体中构造子窗体对象时,将父窗体传递过去: 如:FrmSub frm=new FrmSub(this);//this代表父窗体 2.将父窗体中要访问的变量和方法修改为public 3.在子窗体 ...

  4. python 数字、字符串、列表常用函数

    一.数字的标准类型: cmp():比较两个数的大小:返回值(-1,0,1). str():数字转化成字符串. type():返回数字类型. 转换工厂函数: int(obj,base=10) long( ...

  5. Codeforces 559A 第六周 O题

    Description Gerald got a very curious hexagon for his birthday. The boy found out that all the angle ...

  6. mysql语句大全

    转自:http://www.cnblogs.com/yunf/archive/2011/04/12/2013448.html   1.说明:创建数据库 CREATE DATABASE database ...

  7. 51nod 计算N!的位数

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1130 对于这类问题:斯特林近似公式:     百度百科的证明:http: ...

  8. C#中的委托与事件 笔记

    1.委托是类型安全的回调函数,是将方法作为方法参数.委托可以注册多个方法:委托就是一个  multicastdelegate类,可以通过=赋值,+=添加方法(对象方法与静态方法),内部使用Delega ...

  9. 【转】android 选取图片

    转自:http://www.cnblogs.com/top5/archive/2012/03/06/2381986.html 这几天 在学习并开发android系统的图片浏览 音频 视频 的浏览 由于 ...

  10. [设计模式] 7 桥接模式 bridge

    #include<iostream> using namespace std; class AbstractionImp { public: virtual ~AbstractionImp ...