钩子是编程里一个常见的概念,非常的重要。它使得系统变得非常容易拓展(而不用理解其内部的实现机理,这样可以减少很多工作量)。只要有一个钩子样本,能很容易仿照第一个钩子快速的编写第二个钩子,这里对钩子进行一个简单的理解。

下面是一个最简单的代码例子:

<?php

class Test
{
public static function example()
{
$arr = array(1,2,3,4,5,6);
echo '我是一个钩子测试<br>';
echo 'hello<br/>'; echo '<pre>';
print_r($arr);
echo '</pre>';
}
} Test::example();

浏览器运行测试输出:

我是一个钩子测试
hello
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)

一个Test类里面,写了一个example方法。本来这个example的方法非常简单,就是输出hello,但是在这之前,我们还有其他的事情要做(这里我假定在输入hello之前,有一个字符串要输出,并且在之后有个数组要输出)。

我们现在有2种写法: 
第一:直接在方法里实现我们需要的功能(就像上面代码那样) 
但是这种方式有个问题,就是我们每次更改系统,都需要去更改系统的核心部分(我们假定Test是系统的核心部分),这样会需要我们每次改动都要跳到类Test内部去改动,开发成本非常大,而且代码全部在一起非常不好维护。 
第二:我们封装一个execute方法

function execute($params)
{
if(is_array($params)){
echo '<pre>';
print_r($params);
echo '</pre>';
}else{
echo $params;
}
}

这样我们实现的时候,方便了很多,Test类可以简化成:

class Test
{
public static function example()
{
execute('我是一个钩子测试<br>');
echo 'hello<br/>'; $arr = array(1,2,3,4,5,6);
execute($arr);
}
}

但是现在仍然有个问题,我们改动的时候,仍然要去系统内部改动(如果是简单的数组和字符串,是可以进行配置,但是如果是复杂的逻辑处理,配置行不通)。 
我们想写一个类(通过这个类,向系统发送消息的时候,系统可以直接调用我们的类,而且我们的类只要遵循一定的规则来设计,就和原系统是相容的)。 

做了改进设计出如下钩子格式:

<?php

/**
* 钩子类
*/
class Hook
{
static public function execute($type, $model='')
{
if($model == ''){
$m = new Hello();
}else{
$m = new $model();
} if($type == 'string'){
$m->string();
}elseif($type == 'arr'){
$m->arr();
}
}
} class Test
{
public static function example()
{
Hook::execute('string');
echo 'hello<br/>';
Hook::execute('arr');
}
} 我们只要改动一个外部的Hello类,就可以实现对系统内部的控制了
class Hello
{
public function string()
{
$str = '我是一个钩子测试<br>';
echo $str;
} public function arr()
{
$arr = array(1,2,3,4,5,6);
echo '<pre>';
print_r($arr);
echo '</pre>';
}
} Test::example();

从上面可以看出,组成一个单独的类,系统的内部固定了后,外部可以写各种类,进行钩子的实现。现在写了一个Hello类,假如需要拓展一个World类,同样可以仅仅改动Hook,而不用去改动Test内部,只要我们定义一个抽象类:

abstract class lan
{
abstract function string();
abstract function arr();
}

然后让所有的拓展类,比如Hello类或者World类继承这个抽象类,就可以直接写个扩展。

PHP的钩子实现解析的更多相关文章

  1. 关于thinkphp中Hook钩子的解析

    在tp框架下的Library/Think 下有一个Hook类,这个是用来以插件形式来实例化类并且执行方法的 static private  $tags       =   array(); 这里有一个 ...

  2. python---tornado钩子预留解析

    在tornado.web.RequestHandler类中的初始构造方法中: class RequestHandler(object): """Base class fo ...

  3. [转]Spring中property-placeholder的使用与解析

    我们在基于spring开发应用的时候,一般都会将数据库的配置放置在properties文件中. 代码分析的时候,涉及的知识点概要: NamespaceHandler 解析xml配置文件中的自定义命名空 ...

  4. Spring中 <context:property-placeholder 的使用与解析 .properties 配置文件的加载

    转: Spring中property-placeholder的使用与解析 Spring中property-placeholder的使用与解析 我们在基于spring开发应用的时候,一般都会将数据库的配 ...

  5. Spring中property-placeholder的使用与解析

    Spring中property-placeholder的使用与解析 我们在基于spring开发应用的时候,一般都会将数据库的配置放置在properties文件中. 代码分析的时候,涉及的知识点概要: ...

  6. 深入浅出 Vue.js 第九章 解析器---学习笔记

    本文结合 Vue 源码进行学习 学习时,根据 github 上 Vue 项目的 package.json 文件,可知版本为 2.6.10 解析器 一.解析器的作用 解析器的作用就是将模版解析成 AST ...

  7. [No000098]SVN学习笔记5-分支,合并,属性,补丁,锁,分支图

    行结束符和空白选项 在项目的生命周期中,有时可能会将行结束符由 CRLF 改为 LF,或者修改一段代码的缩进.不幸的是这样将会使大量的代码行被标记为已修改,尽管代码本身并没有被修改.这里列出的选项将会 ...

  8. python 全栈开发,Day92(编程式的导航,vue页面布局,marked包的使用)

    昨日内容回顾 1. 组件间的传值 1. bus --> 空Vue对象 通过向bus对象抛出自定义事件的方式在组件间传递信息 2. 注意事项: 1. bus.$on()应该在组件mounted(挂 ...

  9. 基于vue-cli项目添加服务端渲染

    两个示例的git地址: 1. 我的环境 2. 方式一:使用prerender-spa-plugin插件获得SSR的效果. 2.1 说明 2.2 初始化 1 vue init webpack vue-p ...

随机推荐

  1. URAL 1416 Confidential (最小生成树+次小生成树)

    Description Zaphod Beeblebrox - President of the Imperial Galactic Government. And by chance he is a ...

  2. linux学习记录.4.常用命令

    帮助command --help    获取‘command‘命令的帮助 目录与文件 cd /home    进入‘home’目录 cd ..    返回上一级目录 cd       进入个人目录 c ...

  3. java所搜引擎slor学习笔记(一)

    java搜索引擎有很多,比较熟悉的就是slor和lucene. luncene: 概念:全文检索是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置.当用户查 ...

  4. 【CTF WEB】文件包含

    文件包含 题目要求: 请找到题目中FLAG 漏洞源码 <meta charset='utf-8'> <center><h1>文件阅读器</h1>< ...

  5. 公司内网yum源

    新增yum源配置文件 vi /etc/yum.repos.d/szyum.repo 内容如下: #[redhat6.3] [base] name=redhat63 baseurl=http://10. ...

  6. 事件,继承EventArgs带有参数的委托

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  7. 如何同步删除svn管理的package包目录

    转:https://blog.csdn.net/shiwodecuo/article/details/51754598 eclipse在实际的开发中,当我们的项目由svn进行管理时,若想删除选中的整个 ...

  8. nvm npm node.js的关系

    nvm   npm  node.js都是用来构建reactNativ的项目 nvm管理node.j和npm版本的 node.js管理reactNative开发中所需要的代码库的 npm管理对应node ...

  9. linux创建新用户

    服务器只用root账号会有风险,最好是每个人使用一个账号. 1. 添加用户名 adduser linuxidc 2. 给这个用户名设置新密码 passwd linuxidc 3.授权 个人用户的权限只 ...

  10. scala tuple中的syntactic sugar

    List[Tuple2[String, Int]] // Base List[(String, Int)] // Syntactic sugar List[Tuple3[String, Float, ...