惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
Know Your Adversary
Know Your Adversary
Security Latest
Security Latest
Spread Privacy
Spread Privacy
Project Zero
Project Zero
T
The Exploit Database - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
N
News | PayPal Newsroom
A
Arctic Wolf
NISL@THU
NISL@THU
W
WeLiveSecurity
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News: Ask HN
Hacker News: Ask HN
P
Palo Alto Networks Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
大猫的无限游戏
大猫的无限游戏
L
Lohrmann on Cybersecurity
Last Week in AI
Last Week in AI
T
Threatpost
The Last Watchdog
The Last Watchdog
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
Engineering at Meta
Engineering at Meta
爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
S
Security Affairs
P
Privacy & Cybersecurity Law Blog
B
Blog RSS Feed
AWS News Blog
AWS News Blog
P
Proofpoint News Feed
雷峰网
雷峰网
T
Tenable Blog
Schneier on Security
Schneier on Security
H
Heimdal Security Blog
V2EX - 技术
V2EX - 技术
V
V2EX
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
Latest news
Latest news
Help Net Security
Help Net Security
Jina AI
Jina AI
Stack Overflow Blog
Stack Overflow Blog
The Cloudflare Blog
V
Vulnerabilities – Threatpost
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

博客园 - 东国先生

MongoDB - 安装及相关资料 8种Nosql数据库系统对比 Apache 服务器安装和配置相关资料 ffmpeg: error while loading shared libraries: libavdevice.so.53 亚马逊S3 - The difference between the request time and the current time is too large. Imagick setFont() 不能设置字体问题 当Linux中glibc被无意删除后…… vim终端下中文乱码问题 解决Linux中文乱码 Linux下PHP文件操作提示无权限 还原sql server数据库时,无法获得对数据库的独占访问权 zen-cart开发教程 - 开发Sidebox插件 修改zen-cart下单和付款流程以防止漏单 利用反射设置对象的属性(Property) 【转载】Paypal 标准变量列表 C#中的委托 zen-cart开发教程 - 概述 PHP文件操作函数 2009年终总结
zen-cart开发教程 - 通知者/观察者模式
东国先生 · 2010-03-15 · via 博客园 - 东国先生

      通过重写机制和自动加载机制, Zen-Cart使得二次开发人员能够很方便的向核心代码中增加自己的功能, 然而开发者并不能在不破坏原始代码的基础上随意向Zen-Cart核心代码中的不同地方增加自己的代码. 因此, Zen-Cart引入了通知者/观察者模式(observer/notifier system, ONS), 这给开发人员提供了访问Zen-Cart核心代码, 而不需要破坏其原始文件内容的方式.

    第1节  基类base

      为了实现通知者/观察者模式, 首先引入一个重要的类: base类(class.base.php).

      base类中包含了实现通知者/观察者模式的代码,  因此为了使通知者/观察者模式生效, Zen-Cart中的所有类都被定义为base类的子类, 任意打开一个类文件, 例如language.php,你讲可以看到如所示的代码.  如果你希望你自己的类也能够实现通知者/观察这模式, 请将你的类从base类派生.

class language extends base {
.

    第2节   通知者

      ONS的意图是, 开发者可以写代码, 来等待特定的事件发生, 一旦事件发生, 就执行自己的代码. 那么这些事件如何定义, 什么时候触发呢?

      事件可以通过如下面所示的代码来进行触发.

$this->notify('EVENT_NAME');

    第3节   观察者

      事件已经触发了, 可是这对开发者而言又有何用呢? 为了利用通知者的事件, 我们必须编写代码来监听这些事件. 一般而言, 我们需要将观察者编写成一个类, 并放到目录” includes/classes/observers”下面. 下面, 我们就来看一下如何写一个监听事件的观察者类.

<?php
class myObserver extends base {
function myObserver() {
$this->attach($this, array('NOTIFIER_CART_ADD_CART_END'));
}
function update(&$callingClass, $notifier, $paramsArray) {
... do some stuff
}
}

      从代码中, 可以看到, 我们定义了一个名为myObserver的类, 并且在构造函数中将myObserver类和事件NOTIFIER_CART_ADD_CARD_END(shopping_cart.php)进行了绑定.

当某个事件被触发时, base类将检测是否有观察者类在监听这个事件, 如果有, base类将执行观察者类中的一个方法,  在这里当NOTIFIER_CART_ADD_CARD_END事件被触发后, update方法将会被执行.

     参数说明:

     attach方法.

         &$observer  - 观察者类的引用, 为新的观察者生成一个唯一的ID

         $eventIDArray  -  要监听的事件数组

     update 方法

         &$callingClass – 触发事件的类的引用, 你可以通过该参数访问类中的变量

         $notifier – 触发update通知者名称, 因为可能会监听到多个通知者触发事件

         $paramsArray – 传递的参数, 通知这可能利用该参数向观察者提供一些参数

    第4节   notifier类

      ONS是面向对象的思想而设计, 观察者期望将自己绑定到一个可以在自己方法中进行通知的类, 然而在Zen-Cart中的很多程序事实上并不包含在类中, 例如页面中的代码. 为了使在一般的程序中也能够进行事件的通知, Zen-Cart设计了一个notifier类, 作为全局的一个通知者. 如果你想创建一个类来监听在程序中(例如页面头部文件中的代码)触发的事件, 就应该将notifier加入myObserver类, 如下面代码所示.

class myObserver extends base {
function myObserver() {
global $zco_notifier;
$zco_notifier->attach($this, array('NOTIFY_HEADER_END_CHECKOUT_CONFIRMATION'));
}

    第5节   包含观察者类文件

     值得注意的是”includes/classes/observersdirectory”目录中的文件并不会自动加载, 所以你需要让application_top.php文件能够自动加载myObserver类.在目录” includes/auto_loaders”中增加一个文件”config.freeProduct.php”,文件内容如表格 3‑4 代码所示.

$autoLoadConfig[10][] = array('autoType'=>'class',
'loadFile'=>'observers/class.freeProduct.php');
$autoLoadConfig[90][] = array('autoType'=>'classInstantiate',
'className'=>'freeProduct',
'objectName'=>'freeProduct');

    第6节   通知者/观察者模式编程实例

      有时会遇到的一种需求是, 当客户购买了一定数额的商品后, 如果购买的总金额超过指定的数量, 我们希望给客户一个免费的小赠品.

      通过分析后, 可以知道, 当客户增加了商品到购物车后, 会检测是否购买的数量超过了指定的最低消费数量, 则应该自动将该礼品加到客户的购物车, 而如果客户删掉了购物车中的商品, 同样也需要检测, 如果消费总数量已经小于了最低消费数量了, 则应该自动将该礼品从购物车中删除. 按照传统的编程方式, 要实现这个功能也不难, 但是这将在多处对Zen-Cart的核心代码产生破坏. 现在通过ONS, 我们可以通过一个很简单的自定义类来完成这个功能, 并且不会破坏Zen-Cart的核心代码.

通知者/观察者编程实例

<?php
/**
* Observer class used to add a free product to the cart if the user spends more than $x
*
*/
class freeProduct extends base {
/**
* The threshold amount the customer needs to spend.
* 客户需要消费的总数
* Note this is defined in the shops base currency, and so works with multi currency shops
*
* @var decimal
*/
var $freeAmount = 50;
/**
* The id of the free product.
* 赠品的ID
* Note. This must be a true free product. e.g. price = 0 Also make sure that if you don't want the customer
* to be charged shipping on this, that you have it set correctly.
*
* @var integer
*/
var $freeProductID = 57;
/**
* constructor method
* 构造方法
* Attaches our class to the $_SESSION['cart'] class and watches for 2 notifier events.
*/
function freeProduct() {
$this->attach($this, array('NOTIFIER_CART_ADD_CART_END', 'NOTIFIER_CART_REMOVE_END'));
}
/**
* Update Method
*
* Called by observed class when any of our notifiable events occur
*
* @param object $class
* @param string $eventID
*/
function update(&$class, $eventID) {
if ($_SESSION['cart']->show_total() >= $this->freeAmount && !$_SESSION['cart']->in_cart($this->freeProductID) ) {
$_SESSION['cart']->add_cart($this->freeProductID);
}
if ($_SESSION['cart']->show_total() < $this->freeAmount && $_SESSION['cart']->in_cart($this->freeProductID) ) {
$_SESSION['cart']->remove($this->freeProductID);
}
if ($_SESSION['cart']->in_cart($this->freeProductID)) {
$_SESSION['cart']->contents[$this->freeProductID]['qty'] = 1;
}
}
}
?>

     当然,也许由于开发者也不可能考虑的很周全,有时候在代码中不一定在我们想要的地方都进行了事件通知。遇到这种情况,还是有可能对核心代码做少量修改的。但是通过使用观察者模式,还是可以尽量的避免修改其核心代码。