yii2 学习中
属性:
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>, 来获取更多内容.